Effective c++ 学习笔记(四)

条款04:确定对象被使用前已先被初始化

读取未初始化的值会导致不明确的行为,使程序终止或者行为不可预测。最佳的处理方法是:永远在使用对象之前先将它初始化。
  1. 对内置类型,需要手工完成初始化。
  2. 对其他类型,确保构造函数都将对象的每一个成员初始化。
  3. 规定总是在初值列表中列出所有的成员变量,以免需要区分哪些成员变量无需初值。
  4. 成员初始化次序,基类早于派生类被初始化,成员变量总是以其声明次序被初始化。
class student{
public:
    student(string name, string address);
private:
    string m_name;
    string m_address;
	int m_age;
};
//赋值
student::student(string name, string address)
{
    m_name = name;
    m_address = address;
	m_age = 0;
}
//初始化
student::student(string name, string address)
    :m_name(name),m_address(address),m_age(0)
{
}
c++规定,成员变量的初始化发生在进入构造函数之前。在构造函数内,m_name,m_address都不是被初始化,而是被赋值。
赋值的版本先调用default构造函数为m_name,m_address设初值,然后在对它们赋新值,效率较低。

不同编译单元内non-local static 对象的初始化顺序

static对象,生命周期从被构造出来到程序结束为止,包括:
  1. global对象,
  2. 定义于namespace作用域内的对象,
  3. 在class内、在函数内、在file作用域内被声明为static的对象。
其中函数内的static对象成为local static,其它static对象成为non-local static对象。

编译单元,指产出单一目标文件的源码,基本上它是单一源码文件加上其所含入的头文件。c++对“定义于不同的编译单元内的non-local static对象”的初始化相对次序并无明确定义。 如果某个编译单元内的 non-local static对象的初始化使用了另一个编译单元中的 non-local static对象,而该对象尚未初始化,就会出现错误。
解决问题的方法是:将每个non-local static对象搬到自己的专属函数内(该对象在函数内声明为static),函数返回一个reference指向它所含的对象。此时,non-local static对象被local static 对象替换了。
这种方法可行的原因是:函数内 local static对象会在“该函数被调用期间”初始化。所以以“函数调用”(返回指向 local static对象的引用)替换“直接访问 non-local static对象”,就能保证引用了经过初始化的对象。
student& getStudent()
{
	static student stu("April", "shanghai");
	return stu;
}

总结

  1. 内置型对象手工初始化,因为c++不保证初始化它们。
  2. 构造函数最好使用初始值列表,而不是在构造函数体内赋值操作。初始值列表中变量次序应该与类中声明的次序相同。
  3. 避免“跨编译单元初始化次序”问题,以local static对象替换non-local static 对象。

猜你喜欢

转载自blog.csdn.net/liyazhen2011/article/details/73129046