C++11:初始化
C++11中成员变量的初始化主要包括三类变量:
- 普通成员变量
- 常量
- 静态变量
- 静态常量
- 普通成员变量的初始化
有三种初始化的形式:利用{}/=进行本地初始化;初始化列表;先声明,在构造函数体内进行初始化,其中三种方式可以同存,初始化列表后作用于变量。其中,{}初始化的方式可以防止类型的隐形转换。
例:
#include <iostream>
class wget {
private:
int exm{0};
//int exm = 0;
public:
wget(){
std::cout<<"Default Constructor"<<std::endl;
}
wget(int exm):exm(exm){
std::cout<<"Constructor"<<std::endl;
}
wget(const wget&){
std::cout<<"Copy Constructor"<<std::endl;
}
wget(wget&&){
std::cout<<"Move Constructor"<<std::endl;
}
~wget(){
std::cout<<"Destructor"<<std::endl;
}
friend std::ostream& operator<<(std::ostream& out,const wget&);
};
std::ostream& operator<<(std::ostream& out,const wget& wg){
out<<"Exm: "<<wg.exm;
return out;
}
int main(int argc,char* argv[]){
wget a = wget(1);
wget b = wget();
std::cout<<a<<std::endl;
std::cout<<b<<std::endl;
return 0;
}
- 常量
常量可以通过利用{}/=就地初始化,或者使用初始化列表进行初始化。
class wget {
private:
int exm{0};
//const double price{0};
const double price;
//int exm = 0;
public:
wget(int a=0):price(a){
std::cout<<"Default Constructor"<<std::endl;
}
/*
wget(){
std::cout<<"Default Constructor"<<std::endl;
}
wget(int exm):exm(exm){
std::cout<<"Constructor"<<std::endl;
}
*/
wget(const wget& rhs):price(rhs.price){
exm = rhs.exm;
std::cout<<"Copy Constructor"<<std::endl;
}
wget(wget&& rhs):price(rhs.price){
exm = rhs.exm;
std::cout<<"Move Constructor"<<std::endl;
}
~wget(){
std::cout<<"Destructor"<<std::endl;
}
friend std::ostream& operator<<(std::ostream& out,const wget&);
};
std::ostream& operator<<(std::ostream& out,const wget& wg){
out<<"Exm: "<<wg.exm<<"\n";
out<<"Const Var: "<<wg.price;
return out;
}
- 静态变量
静态变量由于不属于任何一个类实例,因此,静态变量需要在类外进行初始化,并且不应该在声明文件中;
class wget {
private:
int exm{0};
const double price{0};
//const double price;
//int exm = 0;
static int var;
public:
wget(int a=0):price(a){
std::cout<<"Constructor"<<std::endl;
}
wget(const wget& rhs):price(rhs.price){
exm = rhs.exm;
std::cout<<"Copy Constructor"<<std::endl;
}
wget(wget&& rhs):price(rhs.price){
exm = rhs.exm;
std::cout<<"Move Constructor"<<std::endl;
}
~wget(){
std::cout<<"Destructor"<<std::endl;
}
friend std::ostream& operator<<(std::ostream& out,const wget&);
};
int wget::var = 2;
std::ostream& operator<<(std::ostream& out,const wget& wg){
out<<"Exm: "<<wg.exm<<"\n";
out<<"Const Var: "<<wg.price<<"\n";
out<<"Static Var: "<<wget::var;
return out;
}
- 静态常量
静态常量可以在声明时初始化{}/=,以及在类外进行初始化。
class wget {
private:
int exm{0};
const double price{0};
//const double price;
//int exm = 0;
const static int var{2};
public:
wget(int a=0):price(a){
std::cout<<"Constructor"<<std::endl;
}
wget(const wget& rhs):price(rhs.price){
exm = rhs.exm;
std::cout<<"Copy Constructor"<<std::endl;
}
wget(wget&& rhs):price(rhs.price){
exm = rhs.exm;
std::cout<<"Move Constructor"<<std::endl;
}
~wget(){
std::cout<<"Destructor"<<std::endl;
}
friend std::ostream& operator<<(std::ostream& out,const wget&);
};
//const int wget::var = 2;
std::ostream& operator<<(std::ostream& out,const wget& wg){
out<<"Exm: "<<wg.exm<<"\n";
out<<"Const Var: "<<wg.price<<"\n";
out<<"Static Var: "<<wget::var;
return out;
}
- 引用成员
通过使用初始化列表进行初始化,或利用{}/=就地初始化。
class wget {
private:
int exm{0};
const double price{0};
//const double price;
//int exm = 0;
const static int var{2};
int& ref;
public:
wget(int& a):ref(a){
std::cout<<"Constructor"<<std::endl;
}
wget(const wget& rhs):price(rhs.price),ref(rhs.ref){
exm = rhs.exm;
std::cout<<"Copy Constructor"<<std::endl;
}
wget(wget&& rhs):price(rhs.price),ref(rhs.ref){
exm = rhs.exm;
std::cout<<"Move Constructor"<<std::endl;
}
~wget(){
std::cout<<"Destructor"<<std::endl;
}
friend std::ostream& operator<<(std::ostream& out,const wget&);
};
编译器默认生成的函数
C++11中存会自动生成以下几类特殊函数:
- 默认构造函数
- 拷贝构造函数
- 拷贝赋值函数
- 移动构造函数
- 移动赋值函数
- 析构函数
其中,对于默认构造函数,只有没有声明任何一个构造函数时,编译器才会在需要的时候自动生成。
对于拷贝函数(构造和赋值)遵从C++98的语法标准,相互独立,声明了其中一个,编译器在需要的时候仍会自动生成另一个。但是若果声明了移动操作,则拷贝操作会被置为=deleted。
对于移动构造及移动赋值,若未声明拷贝操作、移动操作、析构函数,则会自动生成。
析构函数的自动生成遵从98语法。只是在C++11中,声明为noexcept。
默认规则:声明了拷贝或移动操作,则应该声明所有的拷贝、移动、析构操作。