C++編程語言應用范圍非常廣泛,而且應用方式靈活,在一定程度上提高了編程人員的開發效率。那麼接下來,我們就可以通過以下對C++初始化列表的相關實現方法的掌握,來初步了解這一語言的應用技巧。
先看下面這段程序
- #include < iostream>
- #include < vector>
- using namespace std;
- class array
- {
- public:
- array(int lowbound, int highbound);
- vector< int> data;
- int size;
- int lbound, hbound;
- };
- array::array(int lowbound, int highbound):
- size(highbound-lowbound+1),
- lbound(lowbound),hbound(highbound),
- data(size){}
- int main()
- {
- array a(0,10);
- cout < < a.size < < '\n';
- cout < < a.data.size() < < '\n';
- }
這段程序看不出什麼問題,至少一開始我看不出什麼問題,但是運行的結果讓我吃驚,vector< int> data的長度是一個不確定的大小。
許多人都會說,在函數的C++初始化列表中進行了初始化了麼?怎麼還會沒有長度大小呢!其實是我們忽略了構造函數懂初始化列表的游戲規則,構造函數初始化的順序並不是按照我們看到的在構造函數後面寫的順序,而是按照成員變量在類中的定義的順序,所以上面
- array::array(int lowbound, int highbound):
- size(highbound-lowbound+1),
- lbound(lowbound),hbound(highbound),
- data(size){}
的運行順序是按照下面的代碼的實現順序:
- array::array(int lowbound, int highbound):
- data(size),size(highbound-lowbound+1),
- lbound(lowbound),hbound(highbound) {}
所以當運行data(size)的時候,size還沒有定義,所以在後面的測試程序中輸出的data.size()的時候,就輸出了一個不確定的數。
那麼C++為什麼要這麼做呢?
我們知道,對一個對象的所有成員來說,它們的析構函數被調用的順序總是和它們在構造函數裡被創建的順序相反。那麼,如果允許上面的情況(即,成員按它們在初始化列表上出現的順序被初始化) 發生,編譯器就要為每一個對象跟蹤其成員初始化的順序,以保證它們的析構函數以正確的順序被調用。這會帶來昂貴的開銷。所以,為了避免這一開銷,同一種類型的所有對象在創建(構造)和摧毀(析構)過程中對成員的處理順序都是相同的,而不管成員在C++初始化列表中的順序如何。