C++编译器能否对const返回值执行RVO优化?

12

假设我有以下函数:

#include <string>

std::string const foo()
{
    std::string s = "bar";
    return s;
}

int main()
{
    std::string t = foo();
}

即使 st 的类型与 foo 的返回类型不同,由于 const 差异,编译器是否可以对 t 执行(命名)返回值优化?

(如果 C++03 和 C++11 的答案不同,那么我肯定有兴趣了解 C++03 的答案。)


为什么不包括至少一个编译器的实验结果? - Marc Glisse
@MarcGlisse:好吧,Visual C++ 2008优化掉了它,但我不确定标准是否允许。 - user541686
1个回答

15

对于RVO优化来说,它不会破坏const的承诺,因此没有问题:可以执行RVO。


然而,移动语义受到const的影响。它有效地禁用了移动语义,也就是调用T(T&&)构造函数或移动赋值运算符。因此,一般情况下,不要在返回值上使用const

Scott Meyers最初建议在返回值上使用const,以获得更加合理的编码。

然后Andrei Alexandrescu在他为DDJ撰写的Mojo文章中指出,从此以后,在移动语义中,最好禁止在返回值上使用const,并忽略Scott早期的建议。


现在我从未费心去学习各种专门的RVO缩写,比如NRVO等等。主要原因是这些术语在半路上改变了含义,最初在g++编译器中具有某些自定义功能的含义。这里的术语实在是一团糟。

因此,如果我的术语有误,我应该真正使用其他缩写,请随意更正! :-)


关于移动语义的优点,我同意你的看法。但是这让我想知道:使用const返回值禁用移动语义有什么问题吗?难道RVO(完全避免实例化对象)不比move更好吗?因为move需要实例化对象并进行维护工作才能执行实际的移动操作。 - user541686
@Mehrdad:移动语义由程序员控制,编译器无法干涉,而RVO则由编译器控制,程序员几乎无法干涉。例如,调用可能是一个赋值s = foo()而不是初始化。然后const会阻止移动函数字符串结果的缓冲区:它很可能会被复制,并可能分配另一个缓冲区。 - Cheers and hth. - Alf
好的,但是 如果 我知道正在发生 RVO,从性能上来说,它将永远(在实践中)不会比移动慢,对吧?因此,从性能角度来看,如果你可以确保 RVO,则返回 const 比返回可变的更好? - user541686
@Mehrdad: 嗯,我认为你最好定义一下“更好”的含义。不是每个人都同意当时Scott Meyers的原始建议。对于“更好”的不同定义有所涉及。好的,现在我看到你写了“从性能方面来说”。但是我无法看出const如何改善性能,我的建议是进行测量 - Cheers and hth. - Alf
RVO是否也允许省略move构造函数,还是只允许省略复制构造函数? - user541686
1
@Mehrdad:是的,C++11在省略移动复制构造方面采用相同的规则。这是由§12.8/31规定的:“当满足某些条件时,即使类对象的复制/移动构造函数和/或析构函数具有副作用,实现也允许省略类对象的复制/移动构造。”我想你可以从这里开始理解了。;-) - Cheers and hth. - Alf

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