首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么RVO的要求如此严格?

为什么RVO的要求如此严格?
EN

Stack Overflow用户
提问于 2018-03-20 09:50:10
回答 1查看 541关注 0票数 14

还有一个“为什么std::move必须阻止(未命名的)返回值优化?”问题:

为什么性病::移动防止RVO?解释说,标准明确要求函数的声明返回类型必须与return语句中表达式的类型匹配。这解释了符合编译器的行为;但是,它并没有解释限制的理由。

为什么对于函数的返回类型为Treturn表达式的类型为T&&的情况,RVO的规则不例外

我还意识到,在编译器中实现这些东西并不是免费的。我只是建议允许但不需要这样的例外。

我也知道return std::move(...)是不必要的,因为C++11 已经要求在无法应用RVO时使用移动语义。然而,为什么不容忍一个明确的优化要求,而不是把它变成悲观呢?

(旁白:为什么return-value-optimizationrvo标签不是同义词?)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-03-20 10:12:44

代码语言:javascript
复制
auto foo() -> T&&;

auto test() -> T
{
    return foo();
}

你说在这种情况下,RVO应该被允许应用。但是,请考虑foo的合法实现。

代码语言:javascript
复制
T val;

auto foo() -> T&&
{
   return static_cast<T&&>(val); // because yes, it's legal
}

寓意:只有你知道的真值,你才能确定你有一个暂时的,最重要的,你知道它的确切寿命,这样你才能避免它的构造和破坏。但是对于xvalue(例如T&&返回),您不知道它是否确实绑定到临时值,您不知道该值是何时创建的,何时超出范围,或者即使您知道不能更改它的构造和破坏点,如上面的示例所示。

我不确定我是否完全理解。如果RVO被允许应用于test(),为什么会比测试更糟糕:允许NRVO的T temp = foo(); return temp;

并不是说情况更糟。这是不可能的。在您的示例中,temp是要应用NRVO (即test )的函数中的一个局部变量。因此,它是一个在上下文中完全“已知”的对象,它的生存期是已知的,ctor和dtor的正常点是已知的。因此,它不是在调用方的堆栈帧中创建temp变量,而是在调用方的堆栈帧中创建。这意味着从test的堆栈帧到调用方的堆栈帧没有对象的副本。还请注意,在本例中,foo()完全不相关。它可能是temp初始化过程中的任何东西。

代码语言:javascript
复制
auto test() -> T
{
    T temp = /*whatever*/;

    return temp; // NRVO allowed
}

但是,使用return foo(),您不能仅仅因为无法知道返回引用绑定到哪个对象而删除副本。它可以是对任何对象的引用。

票数 19
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49380956

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档