为什么移动构造函数需要其成员的默认构造函数?

时间:2016-09-02 16:50:43

标签: c++ default-constructor move-constructor

我试图为没有复制构造函数的类实现移动构造函数。我收到一个错误,指出该类成员的默认构造函数丢失了。

这是一个简单的例子来说明这一点:

struct A {
public:
        A() = delete;
        A(A const&) = delete;
        A(A &&a) {}
};

struct B {
        A a;
        B() = delete;
        B(B const&) = delete;
        B(B &&b) {}
};

尝试编译它,我得到:

move_without_default.cc: In constructor ‘B::B(B&&)’:
move_without_default.cc:15:11: error: use of deleted function ‘A::A()’
  B(B &&b) {}
           ^
move_without_default.cc:6:2: note: declared here
  A() = delete;
  ^

为什么这是一个错误?有什么方法吗?

3 个答案:

答案 0 :(得分:23)

  

为什么移动构造函数需要其成员的默认构造函数?

您定义的移动构造函数 default-构造成员。如果您默认构造任何成员,那么这些成员需要默认构造函数。

构造函数(无论是常规,复制还是移动)默认初始化成员初始化列表中未列出的成员,也没有默认成员初始化。 B::a不在移动构造函数的成员初始化列表中(它根本没有初始化列表),并且没有默认成员初始化。

  

周围有什么办法吗?

最简单的说,使用默认的移动构造函数:

B(B&&) = default;

默认移动构造函数move-构造成员。

答案 1 :(得分:17)

使用构造函数的初始值设定项列表初始化A成员。如上所述,移动构造函数使用编译器所说的A的默认构造函数。

B(B&& b) : a(std::move(b.a)) {}

答案 2 :(得分:9)

移动构造函数通常不必提供默认初始化。 您的移动构造函数。

移动构造函数仍然是构造函数。因此,它必须初始化所有子对象。如果您没有提供显式初始化,那么它将尝试默认初始化它们。如果它不能这样做,你会收到错误。

因此,您可以初始化它们(可能从b移动),或者只使用移动构造函数= default并让编译器完成它的工作。