c++ - 在什么情况下,现代编译器不能对函数应用 NRVO 优化?

标签 c++ c++11 move-semantics rvalue-reference copy-elision

总的来说,我想知道现代编译器(例如使用 c++11 的 gcc 4.7 及更高版本)何时以及为何无法应用 NVRO 优化。

编辑:我错误地简化了这段代码,没有返回任何局部变量。下面的 @cookie451 提供了一个更好的示例,请参阅 ideone.com/APySue

我看到了一些代码片段来回答其他类似的问题

A f(A&& v)
{
  return v;
}

他们变成了

A f(A&& v)
{
  return std::move(v);
}

因为他们说传入的分配给左值 v 的右值仍然是右值并且可以 move 。然而,其他人写道,这将删除 NVRO 的能力。这是什么?如果编译器知道正在返回一个临时文件,难道它不能在不 move 任何东西的情况下直接在适当的位置构造它吗?我想我不明白为什么案例 1 会有 NVRO 但案例 2 没有。我可能有错误的事实因此问题。另外,我读到案例 2 是出于这个原因的反模式,你不应该像这样返回 std::move 。任何额外的见解都会有所帮助。有人告诉我,在幕后,编译器将创建如下所示的内容:A& __hidden_​​_ 是对函数的赋值,在本例中为 myValue。

A myValue = f(A());

// behind the scenes pseudo code for direct in place construction

void f(A&& v,  A& __hidden__ )
{
    __hidden__ = v;
    return;
}

最佳答案

两者都不会使用 RVO,因为这是不可能的。问题是: && 仍然只是一个引用。您返回的变量不在您的函数局部范围内!因此,如果没有 std::move,您将进行复制,并使用它进行 move 。顺便说一句,我会建议不要期望每个右值引用都有什么,只要你不是在编写 move 构造函数/赋值运算符或一些完美转发模板代码。只是按值(value)来衡量。在某些情况下,它的开销很小,但实际上不会很重要。它使代码更具可读性。而且更简单,因为调用者可以复制或 move 参数,并且您不必提供额外的 const& 重载。

关于c++ - 在什么情况下,现代编译器不能对函数应用 NRVO 优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18676891/

相关文章:

c++ - 为什么 std::vector 的元素需要 move 构造函数?

rust - Rust 如何提供 move 语义?

c++ - 如何在 C++ 中有效地实现异构不可变对象(immutable对象)的不可变图?

c++ - 在 C++ 中通过引用传递对象

c++ - 如何仅使用标准库编写 XML 解析器?

带有运算符的 std::array 的 C++11 类型别名

c++ - move 构造函数不是继承的,也不是默认生成的

c++ - 使用 ReadFile 对内存位置的访问无效

c++ - C++11 中的 char16_t 和 char32_t 类型

c++ - std::async 正在阻塞/暂停父线程