在C part of C++中,声明一个变量,不一定会被初始化,而一旦进入non-C part of C++,规则有些变化。这就很好的解释了为什么array(来自C part of C++)不被初始化而vector却有此保证(来自STL of C++)。
第二个构造函数相比第一个,最终结果相同,但通常效率更高。第一个版本先调用默认构造函数设置初始值,然后再立刻对他们赋值,第二个则省去了调用默认构造函数的步骤,直接使用实参初始化。
表面上这似乎是个无法决定的状态,而最佳处理方法是:永远在使用对象前将它初始化。对于无任何成员的内置类型,你必须手工完成此事。
int x=0;
const char* text = "A C-style string";
double d;
std::cin >> d;
至于内置类型以外的任何其他东西,则需要构造函数来初始化。规则就是:确保每一个构造函数都将对象的每一个成员初始化。
这个规则很简单,但不要混淆了赋值和初始化。
class Money{
public:
Money();
private:
int thecash;
}
Money::Money(const int cash)
{
thecash = cash; //这是赋值,不是初始化
}
Money::Money(const int 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对象
先被初始化。