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

jay*_*jay 2 c++ move-semantics c++11

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?
Run Code Online (Sandbox Code Playgroud)

son*_*yao 5

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

因为可以通过复制构造函数和复制赋值运算符执行所需的操作.Interface仍然有自我声明的复制构造函数和复制赋值运算符.并且rvalues总是可以被束缚const Interface&.

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

类不必实现移动构造函数来满足此类型要求:接受const T&参数的复制构造函数可以绑定rvalue表达式.

MoveAssignable.

该类型不必实现移动赋值运算符以满足此类型要求:通过值或作为a获取其参数的复制赋值运算符const Type&将绑定到rvalue参数.


顺便说一句:如果您使移动构造函数和移动赋值运算符显式删除,则复制和移动操作都将失败.使用rvalue表达式将选择显式删除的重载,然后失败.使用左值表达式也会失败,因为复制构造函数和复制赋值运算符由于移动构造函数或移动赋值运算符的声明而被隐式声明为已删除.