C++程序员应了解的那些事(54)《深度探索C++对象模型》中的NRV(Named Return Value)优化

//《示例程序》
#include <iostream>
#include <string>
using namespace std;
 
class Trans 
{
public:
	Trans() : a(12) {};
	Trans(int id) : a(0), i(id) {};
	~Trans() {
		cout << "good bye " << i << endl;
	}
	friend std::ostream& operator<<(ostream&, const Trans&);
	friend Trans operator + (const Trans&, const Trans&);
private:
	int a;
	int i;
};
std::ostream& operator<<(ostream& os, const Trans& tra)
{
	return os << tra.a << endl;
}
Trans operator + (const Trans& t1, const Trans& t2)
{
	Trans t(3);
	t.a = t1.a + t2.a;
	return t;
}
int main()
{
	Trans p(1), q(2);
	cout << p + q;
	return 0;
 
}

GCC编译运行结果如下:

VS的执行结果不一样,它的执行结果在0的前面多了一个good bye 3。

       同样的程序在不同的编译器下的执行结果不一样,那么,只有一种解释:编译器在幕后给你干了一些事情。我想到了《深度探索C++对象模型》中的NRV(Named Return Value)优化。

对于函数:

Trans operator + (const Trans& t1, const Trans& t2)
{
	Trans t(3);
	t.a = t1.a + t2.a;
	return t;
}

编译器会将它转换为类似这样:

void operator +(Trans *this, const Trans& t1, const Trans& t2, Trans &__result)
{
    Trans t(3);
	t.a = t1.a + t2.a;
	__result(t);
	return;
}

(以上的代码在变量和函数名上并没有像编译器一样进行转换,这里只关注编译器是如何返回对象的。)
   如果编译器采用NVR优化,代码就会被转换成类似这样:

void operator +(Trans *this, const Trans& t1, const Trans& t2, Trans &__result)
{
    __result.Trans::Trans(3);
	__result.a = t1.a + t2.a;
	return;
}

       因此,如果不采用NVR优化,在返回一个对象时,会再创建一个临时对象用于获取返回值,因此,此函数会产生两个对象,如果采用NVR优化,在返回一个对象时,直接用返回值去取代函数内部的局部对象,此时,函数只产生一个对象。所以,对于VS和GCC的不同,或许可以理解为VS没有采用NVR优化,所以会有两个对象析构,而GCC采用了NVR优化,所以只有一个对象被析构。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值