永远在使用对象之前先将它初始化对于内置类型,必须手工初始化 int x=0; const char* text=”AAA”; double d; cin>>d;//以读取input stream的方式完成初始化 对于内置类型以外的任何东西,初始化责任落在了构造函数身上 要区分赋值与初始化。 考虑不同类的构造函数 class A{int x;int y;string z;}; A(){ x=1; y=2; z=”111”; } 这仅仅是赋值,而初始化应该使用C++的初始化列表 改进如下 class A{int x;int y;string z;}; A() :x(0),y(1),z(“aaa”) { } 因为这样会调用相应对象的构造函数来对对象进行初始化,而赋值的效果是先调用构造函数,再赋值,发生了两次函数调用 对于以上两点,成员初始化次序是固定的。因此不需要担心成员对象初始化之间的依赖链。不过此链会不会发生死锁,就要靠编码人员自己注意了
但另外有一项需要格外注意的问题是,不同编译单元内定义的non-local static对象的初始化次序。
static对象,它的寿命从被构造出来知道程序结束为止。这种对象包括,global对象,定义于namespace作用域内的对象,在classes内,在函数内,在file作用域内被声明为static的对象。 函数内的static对象被称为localstatic对象,其他的static对象被称为non-localstatic对象。 程序结束时,static对象会被自动销毁,也就是它们的析构函数会再main()结束时自动被调用
编译单元 指产出单一目标文件的那些源码 基本上它是单一源码文件加上其所含入的头文件
提出问题:两个源码文件,每一个内含至少一个non-local static对象。如果某编译单元的某个non-localstatic对象的初始化动作使用了另一编译单元内的某个non-local static对象,它所用到的这个对象可能尚未被初始化(由于C++对“定义于不同编译单元的non-local static对象”的初始化次序没有明确的定义)
解决方案:运用类似单例模式的方法,为non-local static对象写专属函数,使其成为local static对象。使用这个手法的基础在于:C++保证,函数内的local static对象会在该函数调用期间首次遇上该对象之定义式时被初始化。所以以函数调用返回reference替换直接访问 non-local static对象,你就获得了保证,保证你所获得的那个reference将指向一个历经初始化的对象。
例如:有一个FileSystem类的对象 static FileSystem fileSys; 改进为用函数调用获得其引用的方式如下 FileSystem& FileSystemLocalInstance(){ static FileSystem fileSys; return fileSys; } |