为什么对象可以被移动"甚至缺少移动构造函数和移动赋值运算符?

时间:2017-07-07 05:27:20

标签: c++ c++11 move-semantics

http://en.cppreference.com/w/cpp/language/rule_of_three

几个月前我开始使用c ++ 11 并且已经看过五条规则。

所以..我开始在每个具有虚析构函数的类上使用default关键字复制构造函数/复制赋值运算符/移动构造函数/移动赋值运算符。

因为规则告诉我如果你声明显式的析构函数,那么你的类就不再有它的隐式移动构造函数和移动赋值运算符了。

所以我认为gcc会因为缺少移动构造函数和移动赋值运算符而向我抱怨下面的类。

但它运作良好!发生了什么?

class Interface {
public:
    virtual ~Interface() = default;  // implicit destructor
};

class ImplA : public Interface {
public:
    virtual ~ImplA() = default; // implicit destructor
};

ImplA first;
ImplA second(first);            // copy constructor, OK. understood it.
ImplA third(std::move(first));  // move constructor, it's OK. Why?
second = first;             // copy assignment, OK. understood it.
second = std::move(first);  // move assignment, it's also OK. Why?

1 个答案:

答案 0 :(得分:5)

  

所以我认为gcc会因为缺少移动构造函数和移动赋值运算符而向我抱怨下面的类。

因为可以通过复制构造函数和复制赋值运算符执行所需的操作。 Interface仍然具有implcitly declared的复制构造函数和复制赋值运算符。并且rvalues始终可以绑定到const Interface&

更准确地说,即使没有提供移动构造函数和移动赋值运算符,Interface仍然是MoveConstructible

  

类不必实现移动构造函数来满足此要求   type requirement:一个带有const T&参数的复制构造函数   可以绑定rvalue表达式。

MoveAssignable

  

该类型不必按顺序实现移动赋值运算符   满足此类型要求:复制赋值运算符   通过值或const Type&获取其参数,将绑定到rvalue   参数。

BTW:如果你明确地移动构造函数并移动赋值运算符delete,那么复制和移动操作都会失败。使用rvalue表达式将选择显式删除的重载,然后失败。使用左值表达式也会失败,因为复制构造函数和复制赋值运算符由于移动构造函数或移动赋值运算符的声明而被隐式声明为已删除。