这里有很多关于何时可以完成 RVO 的讨论,但关于何时实际完成的讨论不多。如前所述,RVO 不能根据标准得到保证,但有没有办法保证 RVO 优化成功或相应的代码编译失败?
到目前为止,当 RVO 失败时,我部分成功地使代码问题链接错误。为此,我声明了复制构造函数而不定义它们。显然,在我需要实现一个或两个复制构造函数(即x(x&&)
和x(x const&)
.
这就引出了我的第二个问题:为什么编译器编写者选择在用户定义的复制构造函数就位时启用 RVO,而不是在只有默认复制构造函数存在时?
第三个问题:是否有其他方法可以为纯数据结构启用 RVO?
最后一个问题(承诺):你知道任何编译器使我的测试代码表现得比我用 gcc 和 clang 观察到的吗?
以下是显示问题的 gcc 4.6、gcc 4.8 和 clang 3.3 的一些示例代码。该行为不依赖于一般优化或调试设置。当然 option--no-elide-constructors
会按照它所说的去做,即关闭 RVO。
#include <iostream>
using namespace std;
struct x
{
x () { cout << "original x address" << this << endl; }
};
x make_x ()
{
return x();
}
struct y
{
y () { cout << "original y address" << this << endl; }
// Any of the next two constructors will enable RVO even if only
// declared but not defined. Default constructors will not do!
y(y const & rhs);
y(y && rhs);
};
y make_y ()
{
return y();
}
int main ()
{
auto x1 = make_x();
cout << "copy of x address" << &x1 << endl;
auto y1 = make_y();
cout << "copy of y address" << &y1 << endl;
}
输出:
original x address0x7fff8ef01dff
copy of x address0x7fff8ef01e2e
original y address0x7fff8ef01e2f
copy of y address0x7fff8ef01e2f
RVO 似乎也不适用于普通数据结构:
#include <iostream>
using namespace std;
struct x
{
int a;
};
x make_x ()
{
x tmp;
cout << "original x address" << &tmp << endl;
return tmp;
}
int main ()
{
auto x1 = make_x();
cout << "copy of x address" << &x1 << endl;
}
输出:
original x address0x7fffe7bb2320
copy of x address0x7fffe7bb2350
更新:请注意,一些优化很容易与 RVO 混淆。像这样的构造函数助手make_x
就是一个例子。请参阅此示例,其中优化实际上是由标准强制执行的。