移动构造函数会自动初始化未列出的成员吗?
will move constructors automatically initialize unlisted members?
如果我有这个class:
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
}
2个移动构造函数之间有什么区别吗?互斥量 m_ 是否在版本 1 中自动初始化,还是我需要像在版本 2 中那样明确列出它?
请注意,我没有交换互斥量,没有必要这样做(我明确地将移动构造函数标记为非线程安全,因为它不能由于其他原因)。
在这种情况下,这两个构造函数之间绝对没有区别。
规则是:未在构造函数的成员初始化列表中列出的每个数据成员都是默认初始化的。对于class类型,这意味着调用默认构造函数。这就是 std::mutex
的情况,因此可以安全地省略初始化 m_()
。
非class 类型(int
、指针等)发挥作用时会有所不同。对于这些,默认初始化不做任何事情(它给它们留下一个不确定的值),所以如果你想要初始化这些成员,你必须在列表中明确列出它们。即使仅使用 ()
作为初始化列出,这也会将其从默认初始化变为 值初始化, 这意味着使用此类类型的零值进行初始化。
如果我有这个class:
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
}
2个移动构造函数之间有什么区别吗?互斥量 m_ 是否在版本 1 中自动初始化,还是我需要像在版本 2 中那样明确列出它?
请注意,我没有交换互斥量,没有必要这样做(我明确地将移动构造函数标记为非线程安全,因为它不能由于其他原因)。
在这种情况下,这两个构造函数之间绝对没有区别。
规则是:未在构造函数的成员初始化列表中列出的每个数据成员都是默认初始化的。对于class类型,这意味着调用默认构造函数。这就是 std::mutex
的情况,因此可以安全地省略初始化 m_()
。
非class 类型(int
、指针等)发挥作用时会有所不同。对于这些,默认初始化不做任何事情(它给它们留下一个不确定的值),所以如果你想要初始化这些成员,你必须在列表中明确列出它们。即使仅使用 ()
作为初始化列出,这也会将其从默认初始化变为 值初始化, 这意味着使用此类类型的零值进行初始化。