c++ 函数返回类对象

当函数返回类对象的时候,c++编译器会进行返回值优化

返回值优化(Return value optimization,缩写为RVO)是C++的一项编译优化技术。即删除保持函数返回值的临时对象。这可能会省略两次复制构造函数,即使复制构造函数有副作用。[1][2]

典型地,当一个函数返回一个对象实例,一个临时对象将被创建并通过复制构造函数把目标对象复制给这个临时对象。C++标准允许省略这些复制构造函数,即使这导致程序的不同行为,即使编译器把两个对象视作同一个具有副作用。[3]

#include <iostream>

struct C {
  C() {}
  C(const C&) { std::cout << "A copy was made.\n"; }
};

C f() {
  return C();
}

int main() {
  std::cout << "Hello World!\n";
  C obj = f();
}

对于函数返回类对象,一种实现办法是在函数调用语句前在stack frame上声明一个隐藏对象,把该对象的地址隐蔽传入被调用函数,函数的返回对象直接构造或者复制构造到该地址上。[4]例如:

struct Data { 
  char bytes[16]; 
};

Data f() {
  Data result = {};
  // generate result
  return result;
}

int main() {
  Data d = f();
}

可能产生的代码如下:

struct Data { 
  char bytes[16]; 
};

Data * f(Data * _hiddenAddress) {
  Data result = {};
  // copy result into hidden object
  *_hiddenAddress = result;
  return _hiddenAddress;
}

int main() {
  Data _hidden; // create hidden object
  Data d = *f(&_hidden); // copy the result into d
}

这引起了Data对象被复制两次。

另一种技术是命名返回值优化(Named return value optimization,NRVO)。[5]NRVO去除了基于栈的返回值的构造与析构。虽然这会导致优化与未优化的程序的不同行为。

struct Data { 
  char bytes[16]; 
};

void f(Data *p) {
  // generate result directly in *p
}

int main() {
  Data d;
  f(&d);
}

大部分C++编译器均支持返回值优化。[1][6][7]在某些环境下,编译器不能执行此优化。一个常见情形是当函数依据执行路径返回不同的命名对象,或者命名对象在asm内联块中被使用:[4][6][8]

#include <iostream>

struct C {
	C(int j) { i = j; }
	C(const C&) { std::cout << "A copy was made.\n"; }

	int i;
};

C  f(bool cond = false) {
	C first(101);
	C second(102);
	// the function may return one of two named objects
	// depending on its argument. RVO might not be applied
	return cond ? first : second;
}

int main() {
	std::cout << "Hello World!\n";
	C obj = f(true);
}

若想看到不进行返回值优化,那么可以在编译的时候添加-fno-elide-constructors,来禁止编译器来进行返回值优化


转载链接:https://zh.wikipedia.org/wiki/%E8%BF%94%E5%9B%9E%E5%80%BC%E4%BC%98%E5%8C%96

其他资料:http://www.informit.com/articles/article.aspx?p=25033&seqNum=3

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值