我想知道复制/移动省略何时适用(或允许应用)显式delete
复制/移动构造函数和非delete
复制/移动构造函数。以下是具体情况:
可以省略明确的
delete
d 复制 ctor 或移动 ctor 吗?delete
是否允许通过跳过d 复制 ctor 和/或delete
d 移动 ctor从另一个相同类型的对象或临时对象构造对象的尝试成功?这是 VC12 中发生的事情(我不确定是否有禁用复制/移动省略的选项):
#include <iostream> struct Foo { Foo() { std::cout << "default ctor\n"; } Foo(Foo const&) = delete; Foo(Foo&&) = delete; }; int main() { // ----Output------ Foo{ Foo() }; // "default ctor" Foo f; // "default ctor" Foo{ std::move(f) }; // error C2280: 'Foo::Foo(Foo &&)' : attempting to reference a deleted function Foo{ f }; // error C2280: 'Foo::Foo(const Foo &)' : attempting to reference a deleted function }
即使 IntelliSense 抱怨
Foo{ Foo() };
:Error: function “Foo::Foo(Foo &&)” ... cannot be referenced – it is a deleted function
,编译器也不会抱怨,因此该行仍然可以编译。为什么
Foo{ Foo() };
有效,但无效Foo{ std::move(f) };
?如果一个电话忽略了移动 ctor,那么另一个电话不应该吗?为什么
Foo{ Foo() };
有效,但无效Foo{ f };
?这种选择性看起来很随意。这种右值引用优于 const 引用(反之亦然)的任意偏好似乎不适用于非 ctor 方法;在调用中,如果delete
d 重载具有比非delete
d 重载更高的重载决议优先级,则delete
d 会阻塞非 d 重载,delete
从而导致编译器错误:struct Bar { void g(int const&) {} void g(int&&) = delete; }; //… Bar b; b.g(2); //error C2280: 'void Bar::g(int &&)' : attempting to reference a deleted function // ^ Would have compiled had function `g(int&&)` been commented out.
根据该逻辑,当参数不是临时参数时, a
delete
dFoo(Foo&&)
不应阻止调用;将具有比在这种情况下更低的重载解决优先级。Foo(Foo const&)
Foo(Foo&&)
Foo(Foo const&)
我在 g++ 4.8 中尝试了相同的
Foo
示例,禁用复制省略(通过 flag-fno-elide-constructors
)并再次启用它。两个 g++ 试验都给出了:error: use of deleted function 'Foo::Foo(Foo&&)'
对于Foo{ Foo() };
和error: use of deleted function 'Foo::Foo(const Foo&)'
为了Foo{ f };
哪个编译器是正确的?