C++中类的构造函数及初始化

简单分析一下C++中类的构造函数和初始化。

一、构造函数

(一)若类中没有显式定义任何构造函数的话,编译器会自动生成两个构造函数和一个重载操作符:

自动生成的构造函数有:

1、默认构造函数,即无参数的构造函数。

2、复制构造函数,即以该类的常引用对象对象为参数的构造函数。

自动生成的重载操作符为:

1、“=”操作符

(二)一旦类中定义了任何构造函数,编译器就不会自动生成默认构造函数。但复制构造函数和“=”重载操作符还是会自动生成。

(三)需要注意的是,若类中有const变量,则无法自动生成默认构造函数(const变量无法初始化),也无法自动生成“=”重载操作符(无法对const变量赋值)。


二、对象的初始化

譬如定义了类MyClass

class MyClass
{
public:
	MyClass(int n){}
};

(一)直接初始化:

	MyClass c1(1);

(二)复制初始化:

	MyClass c2 = 1;

这里实际上调用了两次构造函数。第一次用1初始化了MyClass类的一个临时对象,第二次用这个临时对象通过复制构造函数初始化了MyClass对象c2。

情况许可时,可允许编译器把临时对象优化掉,跳过复制构造函数,直接创建对象。但这并不是编译器的义务。

*需要说明的是:

1、当编译器进行了优化时,其行为与直接初始化一致,而不必与复制初始化一致。譬如在VS2010Debug模式下:

class MyClass
{
public:
	MyClass(int n){
		d = n;
	}
	MyClass(const MyClass &c){
		d = c.d + 1;
	}
	int d;
};

int main() {  
	MyClass c1(1);
	MyClass c2 = 1;
	cout << c1.d << endl;
	cout << c2.d << endl;
	return 0;  
} 
其两次输出均为1。
2、如果在构造函数前声明了explicit,则只允许使用直接初始化。复制初始化的形式会使编译器报错。

所以,上述程序只能改为:

class MyClass
{
public:
	int d;
	explicit MyClass(int n){
		d = n;
	}
	MyClass(const MyClass &c){
		d = c.d + 1;
	}
};

int main() {  
	MyClass c1(1);
	MyClass c2 = MyClass(1);
	cout << c1.d << endl;
	cout << c2.d << endl;
	return 0;  
} 

有趣的是,此时若将复制构造函数的访问权限设为private,则主函数中第二行语句(c2的定义)会报错,表示无法访问复制构造函数。然而若将复制构造函数的访问权限恢复为public,在调试时,其并没有执行复制构造函数,而是同c1一样,使用直接初始化赋值。

即便将代码改成这样:

class MyClass
{
public:
	int d;
	explicit MyClass(int n){
		d = n;
	}
	MyClass(const MyClass &c){
		d = c.d + 1;
	}
};

int main() {  
	MyClass c1(1);
	MyClass c2(MyClass(1));
	cout << c1.d << endl;
	cout << c2.d << endl;
	return 0;  
} 
c2初始化时,仍然只用了直接初始化的方式,调用了一次explicit MyClass(int n)构造函数后,便初始化完毕。

【注:以上两次代码修改在调试时均进行了监视,发现&c2与调用构造函数中的this的值相同】












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值