C++11常规特性之统一初始化和初始化器列表

在c++11以前,程序员,或者初学者经常会感到疑惑关于怎样去初始化一个变量或者是一个对象。
初始化经常使用括号,或者是使用大括号,或者是复赋值操作。
因为这个原因,c++11提出了统一初始化,以为着使用这初始化列表,下面的做法都是正确的。

1
2
3
4
int value[] {1 , 2 , 3};
std::vector<int> vi {2 , 3 , 4 , 56, 7};
std::vector<std::string> cities {"Berlin" , "New York " , "london " , "cairo"};
std::complex<double> c{4.0 , 3.0}; //相当于c(4.0 , 3.0);

一个初始化列表强制使用赋值操作, 也就是为每个变量设置一个默认的初始化值,被初始化为0(NULL 或者是 nullptr)
如下:

1
2
3
4
int i; //这是一个未定义的行为
int i{}; //i调用默认的构造函数为i赋值为0
int *p; //这是一个未定义的行为
int *p{} ;// p被初始化为一个nullptr

初始化类表不会进行隐式转换
例如:

1
2
3
4
5
6
int  x1(5.3); // 5
int x2 = 5.3 //5
int xi{5.0} //精确地 所以会出现error
int x4 = {5.3} // 精确地 所以会出现error
char ci{7};
char c9{9999}; //error 9999不合适是一个char类型

如果是自己想实现初始化列表构造函数,拷贝函数,赋值函数,需要包含initializer_list 这个头文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class MyClass{
public:
MyClass(int a):a_(a){
std::cout << "normal initializer list\n";
}

MyClass(std::initializer_list<int> a):b_(a) {
std::cout << "initializer list constructor\n";
}

MyClass(MyClass& my) {
std::cout << "copy constructor\n";
this->a_ = my.a_;
this->b_ = my.b_;
}

MyClass& operator=(MyClass& my) {
std::cout << "operator = constructor\n";
this->a_ = my.a_;
this->b_ = my.b_;
return *this;
}
private:
int a_;
std::initializer_list<int> b_;
};

下面是初始化以及输出结果:

1
2
3
4
5
6
7
8
9
MyClass ma{1};               // (a)
MyClass mb = {1, 2, 3}; // (b)
MyClass mc(2); // (c)
MyClass md = b; // (d)
MyClass me(c); // (e)
MyClass mf{e}; // (f)
auto l{2, 2, 3,3};
MyClass mh{l}; // (e)
ma = mb; // (h)

输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
initializer list constructor

initializer list constructor

normal constructor list

copy constructor

copy constructor

copy constructor

initializer list constructor

operator = constructor