C++中初始化列表的使用(总结)
Posted lh03061238
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++中初始化列表的使用(总结)相关的知识,希望对你有一定的参考价值。
参考原文链接 https://www.cnblogs.com/dishengAndziyu/p/10906081.html
1,初始化列表是在 C++ 中才引入的;
2,以“类中是否可以定义 const 成员?”这个问题来引入初始化列表:
1,const 这个关键字可以定义真正意义上的常量,也可以在某些情况下定义只读变量;
3,小实验:
1,下面的类定义是否合法?如果合法,ci 的值是什么,存储在哪里?
1 #include <stdio.h> 2 3 class Test 4 { 5 private: 6 const int ci; // const 作用于 C++ 中的成员变量后得到的是只读成员变量,只读成员变量是不可以出现在成员符号左边的;所以会出现第 10 行的错误信息; 7 public: 8 /* 9 Test() // 在这里编译器显示:ci 是一个 const 成员,没有进行初始化;因此如果要初始化 ci 成员变量,必须要在这一行进行,这个时候就让初始化列表出厂了; 10 { 11 ci = 10; // 在这里编译器显示:ci 在这个类中是一个只读的成员变量; 12 } 13 */ 14 15 /* 由上面的语句改换如下 */ 16 Test() : ci(10) // ci 在初始化之后可以改变,因为 ci 在这里只是一个只读的成员变量,仅仅是不能出现在赋值符号左边而已;我们依旧可以通过指针的方式来修改 ci 里面的值; 17 { 18 // ci = 10; 19 } 20 21 int getCI() 22 { 23 return ci; 24 } 25 }; 26 27 int main() 28 { 29 Test t; // 当这里没有手工定义上面程序中的无参构造函数的时候,显示有“未初始化的 const 的成员”的错误; 同时的当这里没有通过类来定义对象的时候,可以通过编译,说明 const 可以修饰 C++ 中的成员变量; 30 31 printf("t.ci = %d ", t.getCI()); 32 33 return 0; 34 }
4,C++ 中提供了初始化列表对成员变量进行初始化,其语法规则为:
1,代码示例:
1 ClassName::ClassName() : m1(v1), m2(v1, v2), m3(v3) // 用 v1, (v1, v2), v3 分别对 m1, m2, m3 初始化; 2 { 3 // some other initialize operation; 4 }
1,初始化列表应该在构造函数的地方使用;
2,构造函数参数列表之后函数体之前定义初始化列表;
3,其作用就是对成员变量进行初始化;
2,注意事项(避免 bug 很重要):
1,成员的初始化顺序与成员的声明顺序相同;
2,成员的初始化顺序与初始化列表中的位置无关;
3,初始化列表先于构造函数的函数体执行;
1,当构造函数的函数体开始执行的时候,对象已经创建完毕了,执行构造函数的函数体仅仅是为了初始化我们这个对象的状态而已;
2,所以说初始化列表既然是用于初始化,那么必须在我们这个类对象创建的同时来进行执行,而不应该是对象已经创建好了才来进行一系列的初始化工作,这一点是有明确差异的,这个差异也就是初始化和赋值之间的差异;
5,初始化列表的使用编程实验:
1 #include <stdio.h> 2 3 class Value 4 { 5 private: 6 // int mi = 0; // 要初始化成员变量,只能使用初始化列表;在构造函 数当中的那是对成员变量赋值,不是初始化; 7 8 int mi; 9 10 public: 11 Value(int i) 12 { 13 printf("i = %d ", i); 14 mi = i; 15 } 16 17 int getI() 18 { 19 return mi; 20 } 21 }; 22 23 class Test 24 { 25 private: 26 /* 27 Value m2(2); // 这种明确的调用一个参数的方式也是有语法错误的; 28 Value m3(3); 29 Value m1(1); 30 */ 31 Value m2; 32 Value m3; 33 Value m1; 34 35 public: 36 /* 37 Test() // 这里编译器显示没有 value 类的无参构造函数来匹配调用; 38 { 39 40 } 41 */ 42 Test() : m1(1), m2(2), m3(3) // 成员变量的初始化必须通过初始化列表来完成; 43 { 44 printf("Test::Test() "); // 初始化列表先于构造函数的函数体执行; 45 } 46 }; 47 48 int main() 49 { 50 Test t; 51 52 return 0; 53 }
6,类中的 const 成员:
1,类中的 const 成员会被分配空间的;在这里注意:(只有编译时 用立即数初始化的才是真的常量,const成员在编译时 没法直接赋值,能不能进符号表 就看编译时是否可以直接知道值,类只是一个模子 所以不可能给模子赋值 只有在创建对象时才可能 因为创建对象时是分配空间的时候)
1,const 成员分配的空间和我们整个类对象分配的空间一致;
2,类中的 const 成员的本质是只读变量;
1,根据编译提供的错误 bug 信息而得来;
3,类中的const 成员只能在初始化列表中指定初始值;
1,编译器无法直接得到 const 成员的初始值,因此无法进入符号表成为真正意义上的常量;
1,因为只能在运行时才来定义对象,调用构造函数,继而来调用初始化列表初始化成员变量;
7,只读成员变量编程实验:
1,代码示例:
1 #include <stdio.h> 2 3 class Value 4 { 5 private: 6 int mi; 7 public: 8 Value(int i) 9 { 10 printf("i = %d ", i); 11 mi = i; 12 } 13 int getI() 14 { 15 return mi; 16 } 17 }; 18 19 class Test 20 { 21 private: 22 const int ci; 23 24 Value m2; 25 Value m3; 26 Value m1; 27 28 public: 29 Test() : m1(1), m2(2), m3(3), ci(100) 30 { 31 printf("Test::Test() "); 32 } 33 34 int getCI() 35 { 36 return ci; 37 } 38 39 int setCI(int v) 40 { 41 int* p = const_cast<int*>(&ci); // 通过指针来操作常量对象; 42 43 *p = v; 44 } 45 }; 46 47 48 int main() 49 { 50 Test t; 51 52 printf("t.ci = %d ", t.getCI()); 53 54 t.setCI(10); 55 56 printf("t.ci = %d ", t.getCI()); 57 58 return 0; 59 }
2,这个实验说明:
1,类中的 const 成员不是真正意义上的常量,它只是只读变量(编译器告诉的);
8,小插曲:
1,初始化与赋值不同:
1,初始化:对正在创建的对象进行初始值设置;
1,初始化的时候,对象还没创建好,在创建的同时,我们将它的值确定了;
2,赋值:对已经存在的对象进行值设置;
1 int main() 2 { 3 int i = 0; // 这是初始化,初始化的时候 i 还不存在; 4 // ... 5 i = 0; // 这是赋值, i 是实际存在的了,并且 i 已经有一个值了,这个时候将 i 的值被改变了 6 }
9,小结:
1,类中可以使用初始化列表对成员进行初始化;
1,类中不能直接初始化成员变量(不论变量为一般的还是类的对象),只能通过初始化列表来初始化;
2,初始化列表先于构造函数体执行;
3,类中可以定义 const 成员变量(这里是变量);
1,const 作用于类的成员后得到的仅是只读变量;
4,const 成员变量必须在初始化列表中指定初始值;
5,const 成员变量为只读变量;
以上是关于C++中初始化列表的使用(总结)的主要内容,如果未能解决你的问题,请参考以下文章
c++师傅领进门,修行靠个人第五篇:C++类和对象中的一些小细节