C++17/20 编译器是否通过复制省略或调用移动构造函数来优化返回本地变量?[复制]

Does a C++17/20 compiler optimize returning a local varaible by copy elision or invoking move constructor? [duplicate]

提问人:xuhdev 提问时间:11/2/2023 最后编辑:xuhdev 更新时间:11/2/2023 访问量:85

问:

假设我们有一个类:

class Foo {
public:
  Foo() = default;
  Foo(const Foo&) = default;
  Foo(Foo&&) = default;
  // other functions...
private:
  // a bunch of data members...
};

C++17/C++20 编译器会优化以下返回语句吗?

Foo CreateFoo() {
  Foo foo;
  // Do more things with foo ...
  return foo;  // Is copy elision used here? If not, would it be optimized as return std::move(foo)?
}
C++ 17 C++ 20 复制省略

评论

0赞 doug 11/2/2023
通常,但不是必需的。请参阅 NVRO
0赞 user17732522 11/2/2023
编译器不需要省略移动,但可以这样做。编译器是否真的会这样做,很大程度上取决于“// 用 foo 做更多事情......”是什么。不能保证在所有情况下都会返回对象,因此不可能总是进行省略,编译器会在不同程度上检测到这一点。(自 C++98 以来,这方面没有任何变化。foo

答:

2赞 NathanOliver 11/2/2023 #1

自 C++11 以来,此行为没有改变。命名对象可以省略,前提是它满足某些要求,但这不是必需的。

需要保证的是,出于重载解析的目的,对象将首先被视为右值,如果失败,则在故障中将恢复到左值重载解析。在这种情况下,这意味着如果命名返回值优化 (NRVO) 省略不发生,则最坏的情况将被移出函数。foo

评论

0赞 xuhdev 11/2/2023
你有什么参考吗?
0赞 user17732522 11/2/2023
自 C++ 98 以来,该行为甚至没有变化(关于省略,而不是隐式移动)。然而,在 C++23 中,return 语句中隐式移动的规则发生了一些重大变化(尽管 OP 只要求 C++17/20)。从 C++23 开始,return 语句中的 id-expression 只是一个 xvalue,如果它是隐式可移动的。不再有两相过载解决方案。
1赞 NathanOliver 11/2/2023
@xuhdev stackoverflow.com/questions/11088023/...... 还有 en.cppreference.com/w/cpp/language/......