c++ - Move ctor 在所有情况下都有效吗?

标签 c++ move-semantics

我刚刚从 https://msdn.microsoft.com/en-us/library/dd293665.aspx 发现了以下代码显示了如何实现 move ctor:

MemoryBlock(MemoryBlock&& other)
   : _data(nullptr)
   , _length(0)
{
   std::cout << "In MemoryBlock(MemoryBlock&&). length = " 
             << other._length << ". Moving resource." << std::endl;

   // Copy the data pointer and its length from the 
   // source object.
   _data = other._data;
   _length = other._length;

   // Release the data pointer from the source object so that
   // the destructor does not free the memory multiple times.
   other._data = nullptr;
   other._length = 0;
}

此代码附带的问题/疑问之一是:如果类 MemoryBlock 包含某个类类型成员变量(例如 someclassvar ),并且如果成员相当大,修改后的 move ctor 中的以下行是否有效(假设此 someclassvar 没有 move ctor)?

MemoryBlock(MemoryBlock&& other)
   : _data(nullptr)
   , _length(0),someclassvar(other.someclassvar)
{
   std::cout << "In MemoryBlock(MemoryBlock&&). length = " 
             << other._length << ". Moving resource." << std::endl;

   // Copy the data pointer and its length from the 
   // source object.
   _data = other._data;
   _length = other._length;
  // someclassvar=other.someclassvar;

   // Release the data pointer from the source object so that
   // the destructor does not free the memory multiple times.
   other._data = nullptr;
   other._length = 0;
   delete other.someclassvar;
}

这里someclassvar = other.someclassvar;我相信这会调用复制赋值运算符,那么这种行为有效吗?另外,如果 someclassvar 同时包含 move 赋值和复制赋值,那么可能会调用哪个?

move vector 在所有此类情况下都会保持有效吗?如果没有,使用复制因子是否更好?

最佳答案

首先,在任何构造函数中,如果可能的话,您应该更喜欢在构造函数的初始值设定项列表中初始化成员。其次,在 move 构造函数中,您应该使用 std::move 来 move 可 move 的成员,或者在不可 move 的情况下复制它们:

MemoryBlock(MemoryBlock&& other)
: _data(std::move(other._data)), 
  _length(std::move(other._length)),
  someclassvar(std::move(other._someclassvar)) {
   // optionally set state of moved object
}

现在 std::move 不会 move 任何对象,而是将它们转换为右值引用。因此,由于重载解析,将会发生两件事:

  1. 如果要 move 的类型具有用户定义的或隐式定义的 move 构造函数,则将调用此 move 构造函数,从而将对象相应地 move 到其新主机。
  2. 如果要 move 的类型没有任何已定义的 move 构造函数,则将调用该类型的复制构造函数。这是因为右值引用可以绑定(bind)到 const 左值引用,因此幸运的是, move 构造函数的复制构造函数可以匹配重载决策。

Live Demo

现在复制分配和 move 分配或多或少是相同的。正在做:

someclassvar = other.someclassvar;

将复制分配other.someclassvarsomeclassvar。为什么?由于过载解析规则。但是,如果您这样做:

someclassvar = std::move(other.someclassvar);

如果someclassvar有一个 move 赋值运算符,那么出于与上面解释的相同的原因,它将被调用。另一方面,如果 someclassvar 没有 move 赋值运算符,则将调用它的赋值运算符。这里不涉及构造函数,因为该语句是一个赋值。

关于c++ - Move ctor 在所有情况下都有效吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36742274/

相关文章:

c++ - 右值的函数重载

java - 接受右值引用作为参数的方法的 Swig 行为

c++ - 当您将文字常量分配给右值引用时会发生什么?

c++ - 在 std::pair 支撑初始化中复制 vs move

c++ - Unordered_map,检查滑动窗口中的阈值

c++ - MSVC 中的不透明指针会生成编译器错误

android - Android上如何录制OpenCV处理过的AR视频?

c++ - 错误 : expected unqualified-id before '{' token

c++ - 使用 lambda 调用的 move 构造函数

c++ - C++ 中的基本年龄询问程序