【问题标题】:Why are the RVO requirements so restrictive?为什么 RVO 要求如此严格?
【发布时间】:2018-08-29 01:48:03
【问题描述】:

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

Why does std::move prevent RVO? 解释说该标准特别要求函数声明的返回类型必须与return 语句中的表达式类型匹配。这解释了符合标准的编译器的行为;但是,它没有解释限制的理由。

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

我也知道在编译器中实现这些东西并不是免费的。我只是建议允许但不是必需的这种例外。

我也知道 return std::move(...) 是不必要的,因为 C++11 already requires that move semantics be used when the RVO can't be applied。然而,为什么不容忍明确的优化请求,而不是将其变成悲观化呢?


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

【问题讨论】:

  • “因为 C++11 已经要求在无法应用 RVO 时使用移动语义。” ——这是一种奇怪的说法。我宁愿把它总结为“C++11 已经要求在 RVO 的条件适用但编译器没有实现它时使用移动语义。”;特别是,如果您尝试执行 return x.y; 其中 x 是局部变量,它将是没有 std::move 的副本(或不同的右值转换)。

标签: c++ c++11 standards rvo return-value-optimization


【解决方案1】:
auto foo() -> T&&;

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

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

T val;

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

道德:只有通过prvalues,你才能确定你有一个临时的,最重要的是你知道临时的确切生命周期,这样你就可以避免它的构建和破坏。但是对于 xvalues(例如T&amp;&amp; return),您不知道它是否确实绑定到临时值,您不知道该值何时创建以及何时超出范围,或者即使您知道您不能像上面的例子一样改变它的构造和销毁点。

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

并不是说它更糟。这是不可能的。在您的示例中,temp 是您要应用 NRVO 的函数中的局部变量,即test。因此,它是test 上下文中完全“已知”的对象,它的生命周期是已知的,ctor 和 dtor 的法线点是已知的。因此,不是在test 的堆栈帧中创建temp 变量,而是在调用者的堆栈帧中创建。这意味着从test 的堆栈帧到调用者的堆栈帧没有对象的副本。另请注意,在此示例中 foo() 完全无关紧要。在temp的初始化中可能是任何东西:

auto test() -> T
{
    T temp = /*whatever*/;

    return temp; // NRVO allowed
}

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

【讨论】:

  • 我不确定我是否完全理解。如果允许将 RVO 应用于 test(),为什么会比 test 更糟糕:T temp = foo(); return temp; 允许 NRVO?
  • 这是否意味着按值返回比使用移动语义返回更有效?我的理解是,RVO 可能会将返回值实现为参数引用。填充这个参考对象会比移动对象更快,对吧?
  • @Zebrafish 通过复制省略直接构造对象,避免了复制,也避免了移动,所以是的,它比移动更有效。
  • @bolov: 一个请求:你能去rvo tag's synonyms page 并建议return-value-optimization 作为同义词吗?正如 jamesdlin 在他的问题中指出的那样,它们还不是同义词有点愚蠢,但是当然,由于它们不经常使用,很少有人同时具有建议同义词所需的代表和答案分数地点。
  • @ShadowRanger 不能这样做,因为建议将返回值优化作为复制省略的同义词——我认为这是不正确的。打开的元(有点,添加了一个旧问题的答案):meta.stackoverflow.com/a/371346/2805305
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-26
  • 2011-12-27
  • 2020-11-26
  • 1970-01-01
  • 2011-01-27
  • 2017-12-19
相关资源
最近更新 更多