例如:
在接受的答案https://stackoverflow.com/a/14623480/1423254中,
复制省略和RVO仍可在不移动的情况下用于类 构造函数?
是的,RVO仍然起作用。实际上,预期编译器会选择: RVO(如果可能)
在接受的答案https://stackoverflow.com/a/38043447/1423254中,
在无保证的复制省略规则下,这将创建一个临时的, 然后从该临时变量移至函数的返回值。那 可以取消移动操作,但是T必须仍然可以进行移动 构造函数,即使它从未使用过。
重点是,我认为RVO和“左值移动”(或如何称呼它们)是两个完全独立的操作,但是我的同事告诉我,要插入RVO,返回的类需要一个move构造函数。因此,我检查了互联网和SO,显然无法迅速找到该信息...
答案 0 :(得分: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()};
}
答案 1 :(得分:1)
否,如果可以访问副本构造函数。
在C ++ 17之前并保证复制删除, 必须有移动构造函数或复制构造函数才能使代码合法。 Elision只是一种优化,不会影响代码是否会编译。
也就是说,有两个步骤:
return <expr>;
是否合法,在C ++ 17之前,该语句要求(禁止转换)存在复制构造函数或在存在临时构造函数的情况下移动构造函数,可访问。考虑到这一点,让我们回顾一下引号:
在没有移动构造函数的情况下,复制省略和RVO是否仍适用于类?
是的,RVO仍然起作用。实际上,编译器应该选择:RVO(如果可能)
应在合法代码的上下文中理解“是”。如果代码无法编译,那么问题就没有意义了。
在无保证的复制省略规则下,这将创建一个临时变量,然后从该临时变量移至函数的返回值。可以省略该移动操作,但是T仍然必须具有可访问的move构造函数,即使它从未使用过。
这是捷径;尝试考虑可能没有移动构造函数的语句来构造句子,因此,复制构造函数的后备内容只会使解释变得混乱,OP并未表示正在考虑这种情况。