为什么g++这里没有启用RVO?
考虑一下测试代码:
#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)
我期望编译器使用 RVO 机制来消除每个 COPY CTOR 调用,以避免复制函数 create( 的返回值和参数) )
。为什么事实并非如此?
Consider that TEST code:
#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());
}
Compiling with:
g++ -O3 rvo.cpp -o rvo
The output is:
$ ./rvo
Klass()
create(Klass a)
Klass(const Klass& right)
I was expecting the compiler to use the RVO mechanism in order elide every COPY CTOR call, to avoid copying the return value AND the parameter of the function create()
. Why isn't it the case?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
仅当您将临时参数作为函数参数传递时,该标准才允许复制省略。
您期望的两个省略在下面以粗体显示:
返回值没有发生这种情况,因为非易失性名称是函数参数。
已经发生在
create
参数的构造中,否则你会看到:The standard allows copy elision only in case where you pass a temporary as a function argument.
The two elisions you're expecting are bolded below:
It didn't happen for the return value because the non-volatile name was a function parameter.
It has happened for the construction into
create
's parameter, otherwise you'd have seen:您看到的副本是“create”函数中“return”语句的副本。 RVO 无法消除它,因为无法直接构造返回值。您请求“返回”。这里需要一份副本;没有它就无法返回对象。
用标准的话说,不满足 [C++11: 12.8/31] 的以下条件
。原因,这不是一个任意的规则,它是有道理的从实现的角度来看,因为这是函数参数无法做到的:
您正在复制函数参数。您无法在不内联的情况下删除此副本,因为参数在进入函数之前已经存在,因此您不能直接将该对象构造到返回值中。
The copy you see is a copy for the "return" statement in the "create" function. It cannot be eliminated by RVO, as it is not possible to construct the return value directly. You requested to "return a". A copy is needed here; there is no way to return an object without it.
In a standard speak, following condition of [C++11: 12.8/31] is not met
As for the reasons, it is not an arbitrary rule, it makes sense from implementation point of view, as this is what is not possible to do with a function parameters:
You are copying the function parameter. You cannot elide this copy without inlining, as the parameter already exists before you enter the function, therefore you cannot construct that object into the return value directly instead.