C++临时对象、复制构造函数以及析构函数的关键点分析

class human
{
public:
	human()
	{
		cout << "construct " << endl;
		human_num++;
	}
	static int human_num;
	~human()
	{
		human_num--;
		cout << "delete " << this << " ";
		print();
	}
	void print()
	{
		cout << "human num is : " << human_num << endl;
	}
	human(const human& b)
	{
		cout << "copy construct" << endl;
		human_num++;
	}
};
int human::human_num = 0;

human f1(human x)
{
	cout << "x.print ";
	x.print();

	return x; //返回不创建临时对象,只调用复制构造函数初始化h2//涉及RVO和NRVO优化
}

int main()
{
	human h1;
	h1.print();
	human h2 = f1(h1);

	h2.print();

	return 0;
}

程序输出:3次构建对象,3次析构对象

construct //构建h1
human num is : 1
copy construct //按值传递参数,调用复制构造函数 构建形参x
x.print human num is : 2
copy construct  //return x调用复制构造函数  构建并初始化h2
delete 010FFC54 human num is : 2 //析构局部变量x ,对x跟踪地址是010FFC54 
human num is : 2  //h2.print();
delete 010FFD4B human num is : 1 //析构h2  h2跟踪地址为010FFD4B 
delete 010FFD57 human num is : 0 //析构h1  h1跟踪地址为010FFD57 

分析:
前几行基本分析都在上述程序输出中指明,
最后两行是h2和h1的析构
注意 这里要重点强调的是return x为什么没有创建临时对象,不同于普通的赋值,这里是初始化一个对象就不创建临时对象。

具体原因涉及编译器优化(RVO和NRVO)。 RVO (return value optimization) 和NRVO (named return value optimization) 是C++在处理 “返回一个class object的函数”时常用的优化技术,主要作用就是消除临时对象的构造和析构成本。
gcc中有一个-fno-elide-constructors的命令,可以去掉任何返回值优化。

如果这样写:

human h2;
h2 = f1(h1);
这将创建一个临时对象用于赋值给h2,除了析构局部变量x,也将析构该临时对象

最终输出如下:4次构建对象,4次析构对象,比上面例子的函数返回值用来初始化对象少一次构建析构
construct
human num is : 1
construct
copy construct //构建x
x.print human num is : 3
copy construct //return创建一个临时对象存储返回结果
delete 006FF854 human num is : 3 //函数调用结束,析构x,因为此时临时对象还有用
delete 006FF880 human num is : 2 //析构return产生的临时对象
human num is : 2
delete 006FF958 human num is : 1
delete 006FF964 human num is : 0

结束

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值