在 C++11 中,RVO 需要移动 constructor/assignment 吗?

Is a move constructor/assignment needed for RVO to kick in in C++11?

例如:

在已接受的答案中 ,

Does copy elision and RVO would still work for classes without move constructors?

Yes, RVO still kicks in. Actually, the compiler is expected to pick: RVO (if possible)

在接受的答案中 ,

Under non-guaranteed copy elision rules, this will create a temporary, then move from that temporary into the function's return value. That move operation may be elided, but T must still have an accessible move constructor even if it is never used.

关键是我认为 RVO 和“左值移动”(或如何称呼它们)是 2 个完全独立的操作,但我的同事告诉我,要启动 RVO,class 返回需要一个移动构造函数。所以我检查了互联网和 SO 显然,无法快速找到信息...

简答:没有。

RVO 在 C++11 之前也存在,当时还没有 "move constructor" 这样的东西。在这种情况下,复制构造函数是唯一的要求。

您引用的 "Under non-guaranteed copy elision rules..." 段落指的是 pre-C++17 世界,其中 "mandatory copy elision" 还不是语言的一部分.

自 C++17 起,编译以下代码(保证零 copies/moves):

struct foo
{
    foo() = default;
    foo(const foo&) = delete;
    foo(foo&&) = delete;
};

foo get_foo() { return foo{}; }

int main()
{
    foo f{get_foo()};
}

否,如果复制构造函数可用。

在 C++17 之前并保证 copy-elision、 移动构造函数或复制构造函数必须可用以使代码合法。 Elision 只是一种优化,并不影响代码是否可以编译。

即有two-steps个过程:

  • 评估语句 return <expr>; 是否合法,在 C++17 之前要求(禁止转换)存在复制构造函数,或者在存在临时构造函数的情况下存在移动构造函数 和访问
  • 如果可能,应用 Return 值优化并省略对所述构造函数的调用。

考虑到这一点,让我们回顾一下引文:

Does copy elision and RVO would still work for classes without move constructors?

是的,RVO 仍然有效。实际上,编译器应该选择:RVO(如果可能)

Yes 应该在合法代码的上下文中理解。如果代码无法编译,那么这个问题就没有意义了。

Under non-guaranteed copy elision rules, this will create a temporary, then move from that temporary into the function's return value. That move operation may be elided, but T must still have an accessible move constructor even if it is never used.

这是一个short-cut;试图在考虑到可能缺少移动构造函数的情况下制定句子,因此回退到复制构造函数只会混淆解释,而且 OP 没有表示正在考虑这种情况。