为什么在最简单的代码上,Visual C++没有执行返回值优化?

15

Visual C++是否不执行返回值优化?

#include <cstdio>
struct Foo { ~Foo() { printf("Destructing...\n"); } };
Foo foo() { return Foo(); }
int main() { foo(); }

我编译并运行它:

cl /O2 test.cpp
test.exe

结果输出:

析构中...
析构中...

为什么没有进行返回值优化(RVO)呢?


4
你可能希望向微软咨询,而不是在StackOverflow上发问。 - David Rodríguez - dribeas
1
@DavidRodríguez-dribeas:嗯,Microsoft的文档说他们可以执行命名 RVO(这更加困难),但我既无法使NRVO工作,也无法使简单的RVO工作。所以我感觉我在这里做错了什么,因为如果他们不支持它,他们就不会提到它(希望如此...) - user541686
@Mehrdad:你有微软文档的链接吗? - Chris Dargis
1
我撤回了我的评论,因为我有一个替代假设,结果证明是不正确的(我认为可能发生了移动构造而不是RVO,但事实并非如此)。如果这个问题对你很重要,我建议在Microsoft Connect上开一个bug。由于这个问题似乎只影响没有非平凡构造函数的类类型,我不确定它是否是一个巨大的问题(而且由于RVO是一种可选的优化,它不是一个符合性问题),但仍然值得报告。 - James McNellis
1
@JamesMcNellis:哦,太棒了,谢谢!https://connect.microsoft.com/VisualStudio/feedback/details/756190/visual-c-return-value-optimization-inhibited-by-trivial-constructor - user541686
显示剩余4条评论
1个回答

16

当我使用这个进行测试:

#include <iostream>
struct Foo { 
    Foo(Foo const &r) { std::cout << "Copying...\n"; }
    ~Foo() { std::cout << "Destructing...\n"; }
    Foo() {}
};

Foo foo() { return Foo(); }

int main() { Foo f = foo(); }

我得到的输出是:

Destructing...

没有调用复制构造函数,只有一个析构函数被调用。


1
嗯...您介意解释一下这段代码和我的代码之间的差异是什么吗? - user541686
6
某些情况下,编译器生成的默认构造函数似乎会阻碍(N)RVO。只要添加自己的默认构造函数,即可获得有效的(N)RVO(例如,如果您添加并调用:Foo bar() { Foo f; return f; },您只需多一个析构函数调用,所以NRVO也将起作用)。 - Jerry Coffin
6
构造函数并不一定需要用户声明:使Foo具有非平凡的默认构造函数或复制构造函数也可以“重新启用”RVO(例如,给它一个类型为std::string的数据成员)。 - James McNellis
1
@JamesMcNellis::O 你都是从哪里学到这些的?我之前从来没有见过这些信息... - user541686
7
底线:编译器只会在拷贝操作可能昂贵到值得消除时才费心去消除拷贝。 - Jerry Coffin
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接