详解C++中对构造函数和赋值运算符的复制和移动操作

2020-01-06 14:26:07于海丽

定义一个空的构造函数方法,该方法采用一个对类类型的右值引用作为参数,如以下示例所示:


MemoryBlock(MemoryBlock&& other)
 : _data(nullptr)
 , _length(0)
{
}

在移动构造函数中,将源对象中的类数据成员添加到要构造的对象:


_data = other._data;
_length = other._length;

将源对象的数据成员分配给默认值。 这样可以防止析构函数多次释放资源(如内存):


other._data = nullptr;
other._length = 0;

为 C++ 类创建移动赋值运算符
定义一个空的赋值运算符,该运算符采用一个对类类型的右值引用作为参数并返回一个对类类型的引用,如以下示例所示:


MemoryBlock& operator=(MemoryBlock&& other)
{
}

在移动赋值运算符中,如果尝试将对象赋给自身,则添加不执行运算的条件语句。


if (this != &other)
{
}

在条件语句中,从要将其赋值的对象中释放所有资源(如内存)。
以下示例从要将其赋值的对象中释放 _data 成员:


// Free the existing resource.
delete[] _data;

执行第一个过程中的步骤 2 和步骤 3 以将数据成员从源对象转移到要构造的对象:


// 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;

返回对当前对象的引用,如以下示例所示:


return *this;

以下示例显示了 MemoryBlock 类的完整移动构造函数和移动赋值运算符:


// Move constructor.
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;
}

// Move assignment operator.
MemoryBlock& operator=(MemoryBlock&& other)
{
 std::cout << "In operator=(MemoryBlock&&). length = " 
    << other._length << "." << std::endl;

 if (this != &other)
 {
  // Free the existing resource.
  delete[] _data;

  // 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;
 }
 return *this;
}