【问题标题】:Why does a move constructor require a default constructor for its members?为什么移动构造函数需要其成员的默认构造函数?
【发布时间】:2017-01-10 20:40:11
【问题描述】:

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

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

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

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

【问题讨论】:

  • 用= default;替换{}
  • 因为A的默认构造函数被删除了,但是B使用了它。
  • 空的移动构造函数不会自动尝试逐个成员移动。您的移动构造函数正在尝试默认构造 a,而不是移动构造它。
  • 嗯,通过删除A 的默认构造函数和复制构造函数,并且不实现除移动构造函数之外的任何其他构造函数,这是否意味着A 对象在它可以之前永远不能被构造移动到另一个A 对象?或者像大括号初始化这样的事情会绕过它?

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


【解决方案1】:

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

您定义的移动构造函数默认构造一个成员。如果您默认构造任何成员,则这些成员需要默认构造函数。

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

有什么办法吗?

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

B(B&&) = default;

默认的移动构造函数移动构造成员。

【讨论】:

    【解决方案2】:

    使用构造函数的初始化列表来初始化A 成员。正如编译器所说,移动构造函数使用A 的默认构造函数。

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

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        猜你喜欢
        • 2011-04-17
        • 2016-12-16
        • 2019-03-01
        • 2016-01-27
        • 2019-01-22
        • 1970-01-01
        • 2012-12-25
        • 1970-01-01
        • 2022-01-09
        相关资源
        最近更新 更多