74 C++对象模型探索。C++关于 初始化成员列表的讨论

零,初始化成员列表在 构造函数 和 copy构造函数中使用

一,何时必须用 初始化成员列表

a.如果这个成员是个引用

b.如果这个成员是const 成员

c.如果这个类继承基类,且这个基类是带参数的构造函数(基类没有缺省的构造函数,缺省的构造函数就是没有参数的构造函数)

d.如果这个成员变量是类类型,且这个类类型是带参数的构造函数(该类没有缺省的构造函数)

二,使用 初始化成员列表 的优势

提高程序运行效率。特别是对于 类类型成员变量的初始化会有明显效率的提升,因此,我们写代码的时候应尽量的使用初始化成员列表。

测试,

class Teacher33 {
public:
	Teacher33() {
		cout << "Teacher33 的 构造函数 被调用 " << this << endl;
	}
	//带有一个参数的构造函数也叫做 类型转换构造函数
	Teacher33(int age) :mage(age) {
		cout << "Teacher33 的 有参数的 构造函数 被调用 " << this << endl;
	}
	Teacher33(const Teacher33 &obj) :mage(obj.mage) {
		cout << "Teacher33 的 copy构造函数 被调用 " << this << endl;
	}
	Teacher33& operator=(const Teacher33 &obj) {
		this->mage = obj.mage;
		cout << "Teacher33 的 operator=函数 被调用 " << this << endl;
		return *this;
	}
	virtual ~Teacher33() {
		cout << "Teacher33 的 析构函数 被调用 " << this << endl;
	}
public:
	int mage;
};


class Teacher34 {
public:
	Teacher34() {
		cout << "Teacher34 构造方法被执行 " << endl;
		
	}
	~Teacher34() {
		cout << "Teacher34 析构方法被执行 " << endl;

	}
	Teacher33 tea33;
};


void main34() {
	Teacher34 tea34;
	//  Teacher33 的 构造函数 被调用 00000083E051F8F8
	//	Teacher34 构造方法被执行
	//	Teacher33 的 析构函数 被调用 00000083E051F8F8
	//从上面可以看到,当实例化Teacher34的时候,是先会将Teacher33 通过构造方法弄出来
}

测试2,

class Teacher33 {
public:
	Teacher33() {
		cout << "Teacher33 的 构造函数 被调用 " << this << endl;
	}
	//带有一个参数的构造函数也叫做 类型转换构造函数
	Teacher33(int age) :mage(age) {
		cout << "Teacher33 的 有参数的 构造函数 被调用 " << this << endl;
	}
	Teacher33(const Teacher33 &obj) :mage(obj.mage) {
		cout << "Teacher33 的 copy构造函数 被调用 " << this << endl;
	}
	Teacher33& operator=(const Teacher33 &obj) {
		this->mage = obj.mage;
		cout << "Teacher33 的 operator=函数 被调用 " << this << endl;
		return *this;
	}
	virtual ~Teacher33() {
		cout << "Teacher33 的 析构函数 被调用 " << this << endl;
	}
public:
	int mage;
};


class Teacher35 {
public:
	Teacher35() {
		cout << "Teacher35 构造方法被执行 " << endl;
		tea33 = 1000;
	}
	~Teacher35() {
		cout << "Teacher35 析构方法被执行 " << endl;
	}
	Teacher33 tea33;
};
void main35() {
	Teacher35 tea35;

	//Teacher33 的 构造函数 被调用 000000F238CFFAA8  当实例化Teacher35的时候,是先会将Teacher33 通过构造方法弄出来
	//	Teacher35 构造方法被执行
	//	Teacher33 的 有参数的 构造函数 被调用 000000F238CFFA18  这说明有临时对象调用了构造函数
	//	Teacher33 的 operator=函数 被调用 000000F238CFFAA8   然后将这个临时对象通过 operator= 赋值给了  tea33
	//	Teacher33 的 析构函数 被调用 000000F238CFFA18   临时对象被析构
	//	Teacher35 析构方法被执行
	//	Teacher33 的 析构函数 被调用 000000F238CFFAA8
}

测试3

class Teacher33 {
public:
	Teacher33() {
		cout << "Teacher33 的 构造函数 被调用 " << this << endl;
	}
	//带有一个参数的构造函数也叫做 类型转换构造函数
	Teacher33(int age) :mage(age) {
		cout << "Teacher33 的 有参数的 构造函数 被调用 " << this << endl;
	}
	Teacher33(const Teacher33 &obj) :mage(obj.mage) {
		cout << "Teacher33 的 copy构造函数 被调用 " << this << endl;
	}
	Teacher33& operator=(const Teacher33 &obj) {
		this->mage = obj.mage;
		cout << "Teacher33 的 operator=函数 被调用 " << this << endl;
		return *this;
	}
	virtual ~Teacher33() {
		cout << "Teacher33 的 析构函数 被调用 " << this << endl;
	}
public:
	int mage;
};


class Teacher36 {
public:
	Teacher36() : tea33(1000) {
		cout << "Teacher36 构造方法被执行 " << endl;
	}
	~Teacher36() {
		cout << "Teacher36 析构方法被执行 " << endl;
	}
	Teacher33 tea33;
};

void main() {
	Teacher36 tea36;

	//Teacher33 的 有参数的 构造函数 被调用 0000002C912FF678
	//	Teacher36 构造方法被执行
	//	Teacher36 析构方法被执行
	//	Teacher33 的 析构函数 被调用 0000002C912FF678

}

//解释:在有初始化列表的时候,在Teacher36中的Teacher33 tea33在Teacher36调用构造方法之前就会直接调用 tea33(1000),也就是说:相比 Teacher35 ,在第一次给Teacher33初始化的时候,就给tea33赋值到位了,节省了在Teacher36()内部的二次给tea33赋值的操作。

三,初始化列表细节探究

说明:

3.1 初始化列表中的代码 可以看做是被编译器安插到构造函数体中的,只是这些代码有些特殊。

3.2 初始化列表中的代码 是在任何用户自己的构造函数体代码之前被执行的。

3.3 初始化列表中的代码 中变量的初始化顺序是 定义顺序,而不是在初始化列表中写的顺序。这里有个坑,容易掉进去,如果有两个变量,一个变量的值传递进去的是100,一个传递进去的是另一个变量的值,要特别注意定义的顺序。

你可能感兴趣的:(c++,开发语言)