【问题标题】:Why object could be "moved" even lacks move constructor and move assignment operator?为什么即使缺少移动构造函数和移动赋值运算符也可以“移动”对象?
【发布时间】:2017-12-11 07:13:21
【问题描述】:

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

几个月前我开始使用 c++11 并且看过五法则。

所以..我开始在每个具有虚拟析构函数的类上放置带有默认关键字的复制构造函数/复制赋值运算符/移动构造函数/移动赋值运算符。

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

所以我认为 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?

【问题讨论】:

  • 看看move ctor,“已删除隐式声明的移动构造函数”部分,您的类不满足其中列出的任何条件。
  • 一切正常。 =default 析构函数等同于隐式析构函数,因此这些类不计入规则 5 中提到的 user-defined 析构函数。
  • 5 规则是一个指导原则。这是因为它经常被需要,而不是因为你应该总是这样做。如果您的虚拟析构函数只是为了使您的类型具有多态性(如您的示例中的情况),则无需创建其他方法,因此。
  • @K.Kirsz 这与参考文献(和 C++ 标准)中的陈述相矛盾。
  • @jay 你的析构函数不是 user-provided 但仍然是user-declared;这意味着编译器不会隐式声明任何移动构造函数和赋值运算符。请参阅链接的“隐式声明的移动构造函数”部分。

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


【解决方案1】:

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

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

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

一个类不必实现一个移动构造函数来满足这个 类型要求:接受const T& 参数的复制构造函数 可以绑定右值表达式。

MoveAssignable

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


顺便说一句:如果你明确地创建移动构造函数和移动赋值运算符delete,那么复制和移动操作都会失败。与右值表达式一起使用将选择显式删除的重载,然后失败。使用左值表达式也会失败,因为复制构造函数和复制赋值运算符被隐式声明为删除,因为声明了移动构造函数或移动赋值运算符。

【讨论】:

  • 值得注意的是,如果你明确地delete移动构造函数,那么移动构造将不再编译。
  • @RustyX 添加。在这种情况下,复制和移动操作都会失败。 (我也试过here
猜你喜欢
  • 2016-05-19
  • 2020-01-23
  • 2017-05-15
  • 1970-01-01
  • 2014-07-09
  • 2015-07-10
  • 2019-09-29
  • 2021-08-18
  • 2020-09-06
相关资源
最近更新 更多