c++ - 移动构造函数会自动初始化未列出的成员吗?

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

如果我有这门课:

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 中那样显式列出它?

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

最佳答案

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

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

当非类类型(int、指针等)发挥作用时,就会出现差异。对于这些成员,默认初始化不会执行任何操作(它会为它们留下不确定的值),因此如果您希望初始化此类成员,则必须在列表中明确列出它们。即使仅使用 () 作为初始化列出,这也会将其从默认初始化转换为值初始化,这意味着此类类型使用零值进行初始化。

关于c++ - 移动构造函数会自动初始化未列出的成员吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38178442/

相关文章:

c++ - 嵌套的 shared_ptr 破坏导致堆栈溢出

c++ - typedef 映射、for 循环调试断言、映射/设置不兼容

c++ - 在 C++ 的父构造函数中调用重写的方法

c++ - 使用 std::cout 将 "\r"写入文件会保存之前覆盖的行

C++ 移动构造函数和作用域

c++11 - 无法运行 move 构造函数

c++ - 在 C++0x 中传递/移动构造函数的参数

c++ - std::cout 的奇怪问题

c++ - 堆上非常大的数组 (Visual C++)

c++ - vector 大小自动失败