0

例如:

在接受的答案https://stackoverflow.com/a/14623480/1423254中,

复制省略和 RVO 是否仍然适用于没有移动构造函数的类?

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

在接受的答案https://stackoverflow.com/a/38043447/1423254中,

在非保证复制省略规则下,这将创建一个临时,然后从该临时移动到函数的返回值。该移动操作可能会被省略,但即使从未使用过,T 仍必须具有可访问的移动构造函数。

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

4

2 回答 2

2

不,如果可以访问复制构造函数。

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

也就是说,有一个两步过程:

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

考虑到这一点,让我们回顾一下报价:

复制省略和 RVO 是否仍然适用于没有移动构造函数的类?

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

应该在合法代码的上下文中理解“是”。如果代码无法编译,那么问题就没有实际意义。

在非保证复制省略规则下,这将创建一个临时,然后从该临时移动到函数的返回值。该移动操作可能会被省略,但即使从未使用过,T 仍必须具有可访问的移动构造函数。

这是一条捷径;考虑到可能缺少移动构造函数并因此回退到复制构造函数的情况下试图制定句子只会使解释变得混乱,并且 OP 没有给出任何迹象表明正在考虑这种情况。

于 2019-06-26T20:19:37.497 回答
1

简短的回答:没有。

RVO 在 C++11 之前也存在,当时没有“移动构造函数”之类的东西。在这种情况下,复制构造函数是唯一的要求。

您引用的“根据非保证复制省略规则...”段落指的是 C++17 之前的世界,其中“强制复制省略”还不是该语言的一部分。

从 C++17 开始,以下代码可以编译(保证零拷贝/移动):

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

foo get_foo() { return foo{}; }

int main()
{
    foo f{get_foo()};
}
于 2019-06-26T17:42:49.517 回答