何时隐式移动构造函数不够好?

时间:2013-06-13 22:40:48

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

隐式移动构造函数何时不够好?

我应该像破坏者和复制构造函数那样对待它,通常只有在我管理自己的内存时才需要它吗?

隐式移动构造函数在这个(非常人为的)场景中是否足够好:

class A
{
private:
    B b;
    std::string name;

public:
    A();
    std::string getName() const {
        return name;
    }

    B getB() const {
        return b;
    }
};

class B
{
private:
    std::vector list;

public: 
    B();
    std::vector getList() const {
        return list;
    }
};

2 个答案:

答案 0 :(得分:24)

此处的答案基于Google搜索结果。

引自Andrzej's C++ blog

> 我什么时候应该为我的班级定义移动构造函数?

  

这在很大程度上取决于你的班级做了什么以及如何实施。首先,对于“聚合”类,为了方便/清晰,仅将其他数据分组,移动构造函数将由编译器隐式生成。考虑以下课程。

struct Country {
  std::string name;
  std::vector<std::string>  cities;
};
     

在典型的C ++结构中,许多特殊的成员函数(如复制构造函数,复制赋值,析构函数)都是自动生成的。这还包括移动构造函数(和移动赋值)。

     

对于更复杂的类,它们封装了它们的实现细节,答案更有趣。移动语义(移动构造函数,移动赋值)的主要目标之一是为编译器提供两个工具,用于实现用户定义类型的值语义(按值传递参数,按值返回):

     
      
  1. 制作两个相同的物品 - 它需要很昂贵。
  2.   
  3. 将一个对象从一个内存位置移动到另一个内存位置 - 它可以是   非常快。
  4.         

    如果您的类可以实现比复制构造函数更快的移动构造函数,那么您应该将其实现为运行时速度优化目的。我们已经看到它是如何实现的对于this link中的向量。但是,并不是所有类型都可以实现比复制构造函数更快的移动构造函数。考虑以下矩阵表示。

    class Matrix {
      std::complex<long double> data[1000][1000];
    };
    
         

    因为矩阵表示所需的所有内存都是在类范围内声明的(与使用堆分配的内存的向量不同),所以无法仅应用少量的赋值。我们需要为每个数组元素进行复制。定义移动构造函数没有意义,因为它不会比复制快。

         

    提供移动构造函数的另一个正当理由是,如果要启用不可复制的类型(因为它类似RAII并且代表资源)仍然需要通过不需要复制的值传递,并存储在STL容器中。 this link更详细地解释了这种独特的所有权语义。

答案 1 :(得分:16)

强制性Rule of Zero答案:设计管理单个资源的类 - 从而覆盖移动/复制/析构函数/赋值 - 或者聚合资源管理器且不需要覆盖的类。