【发布时间】:2015-03-20 10:19:51
【问题描述】:
当按值返回本地对象时,C++ 编译器可能利用移动语义优化不必要的副本(复制省略)。
“可能优化”意味着如果不满足适当的条件,则行为应退回到基于复制的默认按值返回语义。
因此,据我了解,按值返回可复制对象总是有效的。
但编译器(clang 和 gcc)似乎不同意我的解释,如下面的 MWE 所示。
class Foo {
public:
Foo();
Foo(const Foo&);
Foo(Foo&&) = delete;
}
Foo f() { return Foo(); } // error: call to explicitly deleted constructor of 'Foo'
Foo g() { Foo a; return a; } // gcc complains, clang is fine
Foo x = g(); // error: call to explicitly deleted constructor of 'A'
Q1:按值返回是否要求对象是可移动的?
Q2:如果没有,gcc 和 clang 在我的 MWE 上是否表现不正常,还是我错过了其他东西?
【问题讨论】:
-
由于NRVO/RVO可能直接调用构造函数省略移动和复制构造函数。虽然省略了调用,但移动和复制语法错误仍然可以阻止编译。
-
你真的是要声明构造函数
private吗?在Foo中公开它们。 -
"...编译器可能会利用移动语义优化不必要的副本(复制省略)。..." -- 这是错误。 Copy Elison 和 Move Semantics 是两个正交的概念。当您复制 Elison 时,您既没有复制也没有移动。当您没有 Copy Elison 时,您可能会根据情况进行 Copy 或 Move 操作。
-
并且即使省略也必须满足复制或移动的条件,所以如果复制或移动会使用私有或删除的构造函数,则程序格式错误。