C++中初始化列表的使用(總結)


原文鏈接 https://www.cnblogs.com/dishengAndziyu/p/10906081.html

參考鏈接:https://www.cnblogs.com/laiqun/p/5776212.html 

                  https://blog.csdn.net/zzyczzyc/article/details/87542418

                 https://www.cnblogs.com/cthon/p/9178701.html

                http://blog.sina.com.cn/s/blog_4c79cc450100lkzh.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 成員的初始值,因此無法進入符號表成為真正意義上的常量;

         (2)  運行時才來定義對象申請空間,調用構造函數,繼而來調用初始化列表初始化成員變量;

      

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 }
復制代碼

   這個實驗說明:類中的 const 成員不是真正意義上的常量,它只是只讀變量(編譯器告訴的);

   

8。小插曲:

    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 成員變量為只讀變量;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM