我想知道复制/移动省略何时适用(或允许应用)显式delete复制/移动构造函数和非delete复制/移动构造函数。以下是具体情况:
可以省略明确的
deleted 复制 ctor 或移动 ctor 吗?delete是否允许通过跳过d 复制 ctor 和/或deleted 移动 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 方法;在调用中,如果deleted 重载具有比非deleted 重载更高的重载决议优先级,则deleted 会阻塞非 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
deletedFoo(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 };哪个编译器是正确的?