确定对象被使用前已经被初始化
在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.cppclass A{public:std::size_t num()const;};extern A aa;
__________________________________________________________________________________________________
__________________________________________________________________________________________________
b.cppclass B{public:B();};B::B(){std::size_t disk = aa.num();//调用aa对象}B bb;//创建bb对象
___________________________________________________________________________________________________
由于C++对于不同编译单元中的non-local static对象初始化次序没有明确规定,假如bb先于aa被初始化,则它将用到还未被初始化的aa,
这显然是不可取的做法。
解决之道是将aa对象搬到专属函数内。
—————————————————————————————————————————————————————————
a.cppclass A{…};A& aa(){static A a;return a;}
—————————————————————————————————————————————————————————
—————————————————————————————————————————————————————————
b.cppclass B{…}B::B(){std::size_t disk = aa().num();}B bb;//创建bb对象
—————————————————————————————————————————————————————————
这样修改之后,在初始化bb对象时,必然调用aa(),进而保证了aa对象先被初始化。
参考资料:《Effective C++》

浙公网安备 33010602011771号