考虑一下测试代码:
#include <iostream>
using namespace std;
class Klass
{
public:
Klass()
{
cout << "Klass()" << endl;
}
Klass(const Klass& right)
{
cout << "Klass(const Klass& right)" << endl;
}
};
Klass create(Klass a)
{
cout << "create(Klass a)" << endl;
return a;
}
int main()
{
const Klass result = create(Klass());
}编撰:
g++ -O3 rvo.cpp -o rvo产出如下:
$ ./rvo
Klass()
create(Klass a)
Klass(const Klass& right)create()**. i期望编译器使用RVO机制,以避免复制函数的返回值和参数,从而避免对每个复制CTOR调用进行编辑。为什么不是这样?**
发布于 2012-02-15 13:06:00
您看到的副本是"create“函数中的”返回“语句的副本。RVO不能消除它,因为不能直接构造返回值。你要求“归还”。这里需要一个副本;没有它就无法返回一个对象。
在标准情况下,C++11的下列条件: 12.8/31不符合
在具有类返回类型的函数中的
语句中,当表达式为非易失性自动对象(函数或catch-子句参数以外的)的名称与函数返回类型相同的cv-不限定类型时,可以通过将自动对象直接构造到函数的返回值中来省略复制/移动操作。
至于原因,这不是一条武断的规则,从实现的角度来看,这是有意义的,因为这是函数参数不可能做到的:
将自动对象直接构造为函数的返回值
您正在复制函数参数。如果没有内联,则无法删除此副本,因为参数在输入函数之前已经存在,因此不能直接将该对象构造为返回值。
发布于 2012-02-15 13:03:14
该标准只允许在传递临时函数参数的情况下进行复制省略。
您所期望的两种选择如下所示:
[C++11: 12.8/31]:当满足某些条件时,即使对象的复制/移动构造函数和/或析构函数有副作用,也允许实现省略类对象的复制/移动构造器。在这种情况下,实现将省略的复制/移动操作的源和目标视为引用同一对象的两种不同方式,并且该对象的销毁发生在如果不进行优化就会销毁这两个对象的晚些时候。这种复制/移动操作的省略(称为复制省略)在以下情况下是允许的(可以合并以消除多个副本):
在具有类返回类型的函数中的
返回值没有发生这种情况,因为非易失性名称是函数参数。
这种情况发生在create参数的构造中,否则您就会看到:
Klass()
Klass(const Klass& right)
create(Klass a)
Klass(const Klass& right)https://stackoverflow.com/questions/9293726
复制相似问题