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

Dor*_*ord 28 c++ move-semantics c++11

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

我应该把它当作析构函数和复制构造函数来对待它,通常只有在我管理自己的内存时才需要吗?

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

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;
    }
};
Run Code Online (Sandbox Code Playgroud)

tao*_*ocp 24

这里的答案是基于谷歌搜索的结果.

引自Andrzej的C++博客

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

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

struct Country {
  std::string name;
  std::vector<std::string>  cities;
};
Run Code Online (Sandbox Code Playgroud)

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

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

  1. 制作两个相同的物体 - 它需要很昂贵.
  2. 将一个对象从一个内存位置移动到另一个内存位置 - 可以非常快速地进行.

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

class Matrix {
  std::complex<long double> data[1000][1000];
};
Run Code Online (Sandbox Code Playgroud)

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

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

  • @DormoTheNord欢迎您.应该给Andrzej一个信用.我也从你的问题中学到了什么. (3认同)

Cas*_*sey 16

回答的强制性规则:设计管理单个资源的类 - 从而覆盖移动/复制/析构函数/赋值 - 或者聚合资源管理器而不需要覆盖的类.