笔记:条款4:确定对象被使用之前已先被初始化

这是我在阅读Effective c++中认为比较重要的部分,下面给出了我对这一节的理解,并写出对应的比较容易理解的代码。

重要的的类中的构造函数是赋值而不是初始化,对于类类型name,则是先初始化再赋值,对于内置类型nums,编译器不保证会初始化。

class A {
	A(string&name, int nums) {
		name = name;
		nums = nums;
		}
private:
	string name;
	int nums;
};

比起先调用默认构造再调用拷贝赋值,只调用一次拷贝构造是比较高效的,实现方法是指定成员初值列,如下:

class A {
	A(string&name, int nums):name(name),nums(nums) {}
private:
	string name;
	int nums;
};

如果成员变量是constreference,它们就一定要先初始化,然后才能赋值。

static对象其寿命从被构造出来直到程序结束为止,这种对象包括global对象、定义于namespace作用域的对象、在class内,函数内以及file作用域内被声明为static的对象。

在函数内的static对象被称为local-static对象,其余为non-local static对象。

c++对定义于不同的编译单元内的non-local static对象的初始化次序无明确定义。

例如:

 文件1:

class A {
public:
	A();
	int jk = 5;
	int get();
};
extern A a;
class B {
public :
	int mm = 10;
	int get();
}bb;
int B::get() {
	return a.jk;
}

文件2:

class B {
public:
	int m = 10;
	int get();
};
class A{
public:
	A() {}
	int jk = 5;
	int get() {
		return jk;
	}
}a;

int main() {
    B bb;
	cout << bb.get();
}

B中的get需要用到A的对象a,但不确定对象b和对象a谁先初始化,可能导致错误。

解决方法是以local对象替换non-local static对象。以函数调用返回函数内的static 对象的引用,此对象会在被调用时被初始化。

所以修改以上代码如下:

A.h:

class A {
public:
	A(){}
	int jk = 5;
	int get();
};

B.h:

class B {
public:
	int m = 10;
	int get();
};

b.cpp:

#include"A.h"
#include"B.h"
A& tfs() {
	static A a;
	return a;
}

int B::get() {
	return tfs().get();
}

源文件.cpp:

#include"A.h"
#include"B.h"
using namespace std;
int A::get() {
	return jk;
}

int main() {
	B b;
	cout << b.get();
}

请记住

为内置型对象进行手工初始化,因为C++不保证初始化它们。

构造函数最好使用成员初值列,而不要再构造函数本体内使用赋值操作。初值列列出的成员变量,其排列次序应该和它们在class中的声明次序相同。

为免除“跨编译单元之初始化次序”问题,请以local static对象替换 non-local static对象

猜你喜欢

转载自blog.csdn.net/lkq_primer/article/details/81121580