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

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

当复制构造函数的参数类型不是 const 时,通过复制 const 对象进行初始化将产生错误。 反之则不然:如果参数是 const,您可以通过复制不是 const 的对象进行初始化。
编译器生成的赋值运算符遵循关于 const 的相同模式。 除非所有基类和成员类中的赋值运算符都采用 const class-name& 类型的参数,否则它们将采用 class-name& 类型的单个参数。 在这种情况下,类的生成的赋值运算符采用 const 参数。
说明:
当虚拟基类由复制构造函数(编译器生成或用户定义的)初始化时,将只初始化这些基类一次:在构造它们时。
含义类似于复制构造函数的含义。 当参数类型不是 const 时,从 const 对象赋值将产生错误。 反之则不然:如果将 const 值赋给不是 const 的值,则赋值能成功。

移动构造函数和移动赋值运算符
下面的示例基于用于管理内存缓冲区的 C++ 类 MemoryBlock。


// MemoryBlock.h
#pragma once
#include <iostream>
#include <algorithm>

class MemoryBlock
{
public:

 // Simple constructor that initializes the resource.
 explicit MemoryBlock(size_t length)
  : _length(length)
  , _data(new int[length])
 {
  std::cout << "In MemoryBlock(size_t). length = "
    << _length << "." << std::endl;
 }

 // Destructor.
 ~MemoryBlock()
 {
  std::cout << "In ~MemoryBlock(). length = "
    << _length << ".";

  if (_data != nullptr)
  {
   std::cout << " Deleting resource.";
   // Delete the resource.
   delete[] _data;
  }

  std::cout << std::endl;
 }

 // Copy constructor.
 MemoryBlock(const MemoryBlock& other)
  : _length(other._length)
  , _data(new int[other._length])
 {
  std::cout << "In MemoryBlock(const MemoryBlock&). length = " 
    << other._length << ". Copying resource." << std::endl;

  std::copy(other._data, other._data + _length, _data);
 }

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

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

   _length = other._length;
   _data = new int[_length];
   std::copy(other._data, other._data + _length, _data);
  }
  return *this;
 }

 // Retrieves the length of the data resource.
 size_t Length() const
 {
  return _length;
 }

private:
 size_t _length; // The length of the resource.
 int* _data; // The resource.
};

以下过程介绍如何为示例 C++ 类编写移动构造函数和移动赋值运算符。
为 C++ 创建移动构造函数