【问题标题】:will move constructors automatically initialize unlisted members?移动构造函数会自动初始化未列出的成员吗?
【发布时间】:2016-07-04 06:50:40
【问题描述】:

如果我有这门课:

class Foo {
public:
    Foo() = default;

    // version 1 move constructor
    Foo(Foo &&f) : v_() {
        v_.swap(f.v_);
    }

    // version 2 move constructor
    Foo(Foo &&f) : v_(), m_() {
        v_.swap(f.v_);
    }

private:
    std::vector<int> v_;
    std::mutex m_;
};

void bar(Foo &&f) {
    // construct a new object from f
    Foo f2(std::move(f)); // f2's value before calling constructor is undefined
}

这两个移动构造函数之间有什么区别吗?互斥锁 m_ 是否在版本 1 中自动初始化,还是我需要像在版本 2 中一样显式列出它?

请注意,我没有交换互斥体,没有必要这样做(我明确地将移动构造函数标记为 非线程安全,因为它不可能是由于其他原因) .

【问题讨论】:

  • 不,没有区别。
  • 移动构造函数WRT初始化成员没有什么特别的。
  • 只要成员有默认构造函数,您就不需要显式初始化它,例如 POD 不需要,std::mutex 可以。
  • @XerenNarcy 区别不是POD/非POD类型,而是类/非类类型。 POD 结构仍将调用其(概念上的)默认构造函数。当然,然后什么都不做。

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


【解决方案1】:

在这种情况下,这两个构造函数之间绝对没有区别。

规则是:构造函数的成员初始化器列表中未列出的每个数据成员都是默认初始化的。 对于类类型,这意味着调用默认构造函数。这就是 std::mutex 在您的情况下发生的情况,因此可以安全地省略初始化 m_()

当非类类型(int、指针等)发挥作用时会有所不同。对于这些,默认初始化不会做任何事情(它给它们留下一个不确定的值),所以如果你想初始化这些成员,你必须在列表中明确列出它们。即使仅列出 () 作为初始化,这也会将其从默认初始化转变为 值初始化, 这意味着对此类类型使用零值进行初始化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-10
    • 1970-01-01
    • 2014-11-01
    • 2021-12-26
    • 1970-01-01
    相关资源
    最近更新 更多