【问题标题】:How can a type with suppressed move construct/assign still be considered moveable?具有抑制移动构造/分配的类型如何仍被认为是可移动的?
【发布时间】:2017-11-24 02:19:51
【问题描述】:
struct copyable { // and movable
  copyable() = default;
  copyable(copyable const&) { /*...*/ };
  copyable& operator=(copyable const&) { /*...*/ return *this; }
};

由于复制构造函数和复制赋值操作函数是显式定义的,这意味着移动构造函数和移动赋值函数不能被编译器隐式定义,因此不允许移动操作。

请问我上面的理解是否正确?

【问题讨论】:

  • 移动可以看作是不需要保留原始变量的特殊情况。保留原始变量(如复制)不会使移动无效。
  • 为伯纳德的评论添加更多细节:移动后,源变量不能保证为空。 (有些对象甚至可能没有“空”的概念。)当然,它可以是空的,或者它可以是不变的,或者它可以是完全不同的东西,例如它现在可以具有先前在目标变量中的值(在赋值的情况下)。在std::string的情况下,如果是移动前的长字符串,它通常是空的,如果是短字符串,它通常是空的。

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


【解决方案1】:

表示移动构造函数和移动赋值函数不能被编译器隐式定义

是的,没错。

因此不允许移动操作。

不,移动操作仍然可以通过复制构造函数和复制赋值操作符执行(尽管这可能不是您期望的情况),因为右值总是可以绑定到const&

更准确地说,copyable 类仍然是 MoveConstructibleMoveAssignable

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

如果 MoveConstructible 类实现了移动构造函数,它还可以实现移动语义以利用构造后 rv 的值未指定这一事实。

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

如果 MoveAssignable 类实现了移动赋值运算符,它还可以实现移动语义以利用赋值后 rv 的值未指定这一事实。

正如@Curious 所指出的,您可以显式声明移动构造函数和移动赋值运算符delete 以使copyable 不可移动;然后使用右值表达式,将选择deleteed 重载并且编译将失败。

【讨论】:

  • 我认为值得一提的是,明确删除移动构造函数和赋值运算符将如何改变事情
  • @Curious 已添加。
  • 但已删除的移动成员与未删除的副本成员相结合几乎总是一个逻辑错误,因为该类无法满足CopyConstructibleCopyAssignable 的要求(需要从右值复制)。例如,这将不允许从工厂函数按值返回本地左值。指导方针:永远不要删除移动成员:stackoverflow.com/a/38820178/576911
猜你喜欢
  • 1970-01-01
  • 2011-06-16
  • 1970-01-01
  • 2019-08-09
  • 2021-08-25
  • 2012-05-15
  • 1970-01-01
  • 2019-01-24
  • 2017-09-19
相关资源
最近更新 更多