四、确定对象被使用之前已被初始化
当我们声明 int x时,x是否会被初始化为0呢?事实上,这与我们当前用的是C++的哪个部分有关,如果用的是C部分(见effective C++ 读后感(一) 视C++为一个语言联邦),则不保证会初始化,因为C追求的是程序运行速度。而在其他部分,就不这样了。这就能解释为了数组不会被初始化,但vector会。
为了避免使用未初始化的对象而使程序运行结果出错甚至崩溃,但保险的方式就是手工对其进行初始化。比如 int x = 0。对于非内置类型,初始化任务就交给构造函数来完成。一个类的构造函数应该要确保它的所有成员都初始化了。
1.注意区分赋值与初始化
#include <iostream>
using namespace std;
class A {
public:
A() {
cout << "A's constructor" << endl;
}
};
class B {
A a;
public:
B() {
a = A(); //这是赋值,不是初始化
}
};
int main() {
B b;
return 0;
}
在上面的例子中,类B有成员a,我们在B的构造函数中对a进行的是赋值,不是初始化。
运行结果为:
A's constructor
A's constructor
在C++中对象的成员变量初化是发生在构造函数之前。上例虽然最终生成了我们想要的对象,但出现了额外的开销。
最好是利用成员初值列来代替赋值,进行初始化。如:
class A {
int num;
public:
A(): num(0) {}
A(int n): num(n) {}
};
这样效率会高一些。
初始化顺序与声明先后一致,与初值列的顺序无关。
不同编译单元内non-local static 对象的初始化顺序
函数内的static对象称为local static对象,其他static对象为non-local static对象。编译单元是单一源码文件加上其所含头文件。如果有多个源码文件,它们之间如果存在依赖关系,那么被使用的对象可能还没有被初始化,因为这时候对象初始化的先后顺序是不确定的。
通过Singleton可以解决这个问题。