【发布时间】:2014-01-02 14:04:40
【问题描述】:
我想知道复制/移动省略何时适用(或允许应用)显式deleted 复制/移动构造函数和非deleted 复制/移动构造函数。具体如下:
-
一个明确的
deleted 复制ctor 或移动ctor 可以被忽略吗?是否允许通过跳过deleted 复制 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 一个会阻止非deleted 一个,从而导致编译器错误: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.根据该逻辑,当参数不是临时参数时,
deletedFoo(Foo&&)不应阻止对Foo(Foo const&)的调用;在这种情况下,Foo(Foo&&)的重载解决优先级将低于Foo(Foo const&)。 -
我在 g++ 4.8 中尝试了相同的
Foo示例,但禁用了复制省略(通过标志-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 };哪个编译器是正确的?
【问题讨论】:
标签: c++ constructor move-semantics delete-operator copy-elision