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\n", 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\n", 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()\n");  // 初始化列表先于构造函数的函数体执行;
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\n", 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()\n");
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\n", t.getCI());
53     
54     t.setCI(10);
55     
56     printf("t.ci = %d\n", 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 成员变量为只读变量;

猜你喜欢

转载自www.cnblogs.com/lh03061238/p/12312853.html