时间:2022-03-22 10:36:33 | 栏目:C代码 | 点击:次
定义:列表初始化是C++11引入的新标准,目的是统一初始化方式
C++11以前只能使用列表初始化来初始化内置类型数组和POD类型对象,C++11中列表初始化可以用于初始化任何类型对象
注意:区分列表初始化和初始化列表
列表初始化:用{}进行初始化的方式
初始化列表:构造函数体前对对象成员直接进行初始化的列表
initializer_list:一种用于未定参数的轻量STL容器
对内置类型对象、POD对象和类对象的列表初始化实现细节是不同的
class testClass { private: int a; int b; public: testClass() :a(0), b(0) { cout << "default init\n"; } testClass(int a) :a(a), b(a) { cout << "sing-val init\n"; } testClass(int a, int b) :a(a), b(b) { cout << "val init\n"; } testClass(testClass& temp) :a(temp.a), b(temp.b) { cout << "copy init\n"; } testClass& operator=(testClass& temp) { //testClass& newobj = *this; a = temp.a; b = temp.b; cout << "copy assign\n"; return *this; } testClass& operator=(int x) { a = x; b = x; cout << "int-convert assign\n"; //testClass& newobj = *this; return *this; } testClass& operator++() { a++; b++; } void printVal(ostream& os) { os << "a=" << a << "\n"; os << "b=" << b << "\n"; } }; using tc = testClass; tc& makeObj(int x, int y) { return { x,y }; } int main() { tc a(1, 1); //val init tc b{ 1,1 }; //val init tc c = { 1,1 }; //val init tc d = tc{ 1,1 }; //val init cout << endl; tc* e = new tc[2]; //default init *2 cout << endl; tc* f = new tc[3]{ {1,1},{2,2},{3,3} }; //val init *3 cout << endl; tc* g = new tc[5]{ {1,1},{1} }; // val init + sing-val init + default init *3 cout << endl; cout << "testing return val of init_list\n"; tc h = makeObj(2, 2); //val init tc i = h; //copy init i = d; //copy assign i.printVal(cout); return 0; }
以下为运行截图
列表初始化测试
添加initializer_list为参数的构造函数后
testClass::testClass(initializer_list<int> list) :a(0), b(0) { int ab = 1; for (auto it = list.begin(); it != list.end(); it++) { if (ab) a += *it; else b += *it; } cout << "init_list init\n"; } int main() { tc a(1, 1); //val init tc b{ 1,1 }; //val init tc c = { 1,1 }; //val init tc d = tc{ 1,1 }; //val init cout << endl; tc* e = new tc[2]; //default init *2 cout << endl; tc* f = new tc[3]{ {1,1},{2,2},{3,3} }; //val init *3 cout << endl; tc* g = new tc[5]{ {1,1},{1} }; // val init + sing-val init + default init *3 cout << endl; cout << "testing return val of init_list\n"; tc h = makeObj(2, 2); //val init tc i = h; //copy init i = d; //copy assign i.printVal(cout); cout << endl; cout << "testing argument init_list\n"; tc j = { 1,2,3,4,5,6 }; tc k = { 9 }; return 0; }
以下为运行截图
添加init_list后测试截图
由此可见所有列表初始化都调用了含有initializer_list为参数的构造函数,证实了列表初始化是基于隐式转换并以initializer_list为底层实现的构想
C++11的列表初始化还有一个额外的功能就是可以防止类型收窄,也就是C++98/03中的隐式类型转换,将范围大的转换为范围小的表示,在C++98/03中类型收窄并不会编译出错,而在C++11中,使用列表初始化的类型收窄编译将会报错:
int a = 1.1; //OK int b{ 1.1 }; //error float f1 = 1e40; //OK float f2{ 1e40 }; //error const int x = 1024, y = 1; char c = x; //OK char d{ x };//error char e = y;//error char f{ y };//error
列表初始化通过C++11引入的initializer_list容器实现了初始化方式的统一,可以看作一种语法糖
初始化类对象时,通过()调用构造函数的地方都可以完全等价地用{}代替
={}不会生成临时对象再拷贝初始化