確定對象被使用前已經被初始化,確定對象初始化
在C part of C++中,聲明一個變量,不一定會被初始化,而一旦進入non-C part of C++,規則有些變化。這就很好的解釋了為什麼array(來自C part of C++)不被初始化而vector卻有此保證(來自STL of C++)。
表面上這似乎是個無法決定的狀態,而最佳處理方法是:永遠在使用對象前將它初始化。對於無任何成員的內置類型,你必須手工完成此事
int x=0;
constchar* text ="A C-style string";
double d;
std::cin >> d;
至於內置類型以外的任何其他東西,則需要構造函數來初始化。規則就是:確保每一個構造函數都將對象的每一個成員初始化。
這個規則很簡單,但不要混淆了賦值和初始化。
classMoney{
public:
Money();
private:
int thecash;
}
Money::Money(constint cash)
{
thecash = cash;//這是賦值,不是初始化
}
Money::Money(constint cash):thecash(cash)//這才是初始化
{}
第二個構造函數相比第一個,最終結果相同,但通常效率更高。第一個版本先調用默認構造函數設置初始值,然後再立刻對他們賦值,第二個則省去了調用默認構造函數的步驟,直接使用實參初始化。
________________________________________________________________________________________________
C++有著十分固定的成員初始化次序:base classes更早於其derived classes被初始化,而class成員變量總是以其聲明次序被初始化。即使它們在成員初值列中以不同次序出現(很不幸那是合法的),也不會有任何影響。
———————————————————————————————————————————————————————
還有一件事情需要操心,即:不同編譯單元內定義的non-local static對象的初始化次序
static對象包括:global對象,定義於namespace作用域的對象,在class內、在函數內、以及在文件作用域內被聲明為static的對象。
函數內的被稱為local static對象,其他的都是non-local static對象。
多個編譯單元中的non-local static對象的編譯次序C++並未做明確的規定
考慮如下兩個文件 a.cpp,b.cpp。
_________________________________________________________________________________________________
a.cpp
class A{
public:
std::size_t num()const;
};
extern A aa;
__________________________________________________________________________________________________
__________________________________________________________________________________________________
b.cpp
class B{
public:
B();
};
B::B()
{
std::size_t disk = aa.num();//調用aa對象
}
B bb;//創建bb對象
___________________________________________________________________________________________________
由於C++對於不同編譯單元中的non-local static對象初始化次序沒有明確規定,假如bb先於aa被初始化,則它將用到還未被初始化的aa,
這顯然是不可取的做法。
解決之道是將aa對象搬到專屬函數內。
—————————————————————————————————————————————————————————
a.cpp
class A{…};
A& aa()
{
static A a;
return a;
}
—————————————————————————————————————————————————————————
—————————————————————————————————————————————————————————
b.cpp
class B{…}
B::B()
{
std::size_t disk = aa().num();
}
B bb;//創建bb對象
—————————————————————————————————————————————————————————
這樣修改之後,在初始化bb對象時,必然調用aa(),進而保證了aa對象先被初始化。
參考資料:《Effective C++》
來自為知筆記(Wiz)