(筆記):初始化列表之初始化順序


一、前面已經介紹了初始化列表的好處,尤其對於類類型的變量來說,會提高效率,下面來介紹必須放在初始化列表的情況(無關效率問題):

1、常量成員,因為常量(const)只能初始化不能賦值(雖說不可以賦值,但是可以通過指針的方式來訪問修改該值),所以必須放在初始化列表里面。
2、引用類型,引用必須在定義的時候初始化,並且不能重新賦值(這是C++中引用的使用規則,這點與指針是不同的,它在運行時刻不能改變),所以也要寫在初始化列表里面
3、沒有默認構造函數的類類型,因為使用初始化列表可以不必調用默認構造函數來初始化,而是直接調用拷貝構造函數初始化。對於這一點來說,上個筆記(構造函數之初  始化列表)中有記載。因為一個類類型的變量在定義的時候會自動調用默認構造函數進行初始化, 所以當一個類類型的成員變量沒有默認構造函數時,只能在初始化列表 中進行。且是拷貝構造函數在起作用。如下代碼:一個調用默認構造函數和賦值構造函數,另一個調用拷貝構造函數(兩種情況已經在代碼中標注):

 1 #include<iostream>
 2  
 3 using namespace std;
 4 
 5 class Student1 {
 6     public:
 7         int a;
 8             
 9          Student1()                         // 無參構造函數
10         { 
11             cout << "默認構造函數Student1" << endl ;
12         }
13     
14         Student1(const Student1& t1) // 拷貝構造函數
15         {
16             cout << "拷貝構造函數Student1" << endl ;
17             this->a = t1.a ;
18         }
19     
20         Student1& operator = (const Student1& t1) // 賦值運算符
21         {
22             cout << "賦值函數Student1" << endl ;
23             this->a = t1.a ;
24             return *this;
25         }
26  };
27 class Student2
28 {
29     public:
30      
31     Student1 test ;
32     Student2(Student1 &t1){                    //這樣的話調用默認構造函數和賦值構造函數 
33         test  = t1 ;
34     }
35 //     Student2(Student1 &t1):test(t1){}        //這樣的話僅僅調用拷貝構造函數, 
36 };
37 int main()
38 {
39     
40     Student1 A;        //進入默認構造函數 
41     Student2 B(A);    //進入拷貝構造函數 
42 
43 }  

二、初始化順序
初始化順序最好要按照變量在類聲明的順序一致,否則會出現下面的特殊情況
仍然拿上面的代碼作為例子,加入適當的代碼,代碼效果如下:

 1 #include<iostream>
 2  
 3 using namespace std;
 4 
 5 class Student1 {
 6     public:
 7         int a;
 8         int b;
 9         void fprint(){
10             cout<<" a = "<<a<<" "<<"b = "<<b<<endl;
11          }
12          
13          Student1(int i):b(i),a(b){ }    //異常順序:發現a的值為0  b的值為2  說明初始化僅僅對b有效果,對a沒有起到初始化作用 
14 //         Student1(int i):a(i),b(a){ } //正常順序:發現a = b = 2 說明兩個變量都是初始化了的  
15 
16          Student1()                         // 無參構造函數
17         { 
18             cout << "默認構造函數Student1" << endl ;
19         }
20     
21         Student1(const Student1& t1) // 拷貝構造函數
22         {
23             cout << "拷貝構造函數Student1" << endl ;
24             this->a = t1.a ;
25         }
26     
27         Student1& operator = (const Student1& t1) // 賦值運算符
28         {
29             cout << "賦值函數Student1" << endl ;
30             this->a = t1.a ;
31             return *this;
32         }
33       
34  };
35 class Student2
36 {
37     public:
38      
39     Student1 test ;
40     Student2(Student1 &t1){
41         test  = t1 ;
42     }
43 //     Student2(Student1 &t1):test(t1){}
44 };
45 int main()
46 {
47     
48     Student1 A(2);        //進入默認構造函數 
49     Student2 B(A);        //進入拷貝構造函數 
50     A.fprint();            //輸出前面初始化的結果 
51 
52 }  

兩種不同的初始化方法結果如下:

異常初始化順序:

正常初始化順序:

由上面的例子可知,初始化列表的順序要跟你在類聲明的順序要一致。否則像上面的那種特殊情況,有些變量就不會被初始化。經過測試發現,類中變量為下面的情況也是能夠正常初始化的:也就是說,只要成員變量的初始化不依賴其他成員變量,即使順序不同也能正確的初始化。

1 int a;
2 int b;
3 int c;
4 Student1(int i):b(i),a(i),c(i){} 
5 main:
6 Student1 A(2);    
7 A.fprint();

結果:

1 int a;
2 int b;
3 int c;
4 Student1(int i,int j,int k):b(i),a(j),c(k){}
5 main:
6     Student1 A(2,3,4);
7     A.fprint();

結果:

 

歡迎大家關注我的微信公眾號「佛系師兄」,里面會有各種其他技術文章。

比如

反復研究好幾遍,我才發現關於 CMake 變量還可以這樣理解!

更多好的文章會優先在里面不定期分享!打開微信客戶端,掃描下方二維碼即可關注!


免責聲明!

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



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