Reputation: 298
If I have this 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
}
Is there any difference between the 2 move constructors? Does the mutex m_ get initialized automatically in version 1 or do I need to explicitly list it as in version 2?
Note that I'm not swapping the mutexes, there's no need to do that (I'm explicitly marking the move constructor as not thread safe because it can't be due to other reasons).
Upvotes: 2
Views: 129
Reputation: 171117
In this case, there is absolutely no difference between these two constructors.
The rule is: every data member which is not listed in the member initialiser list of a constructor is default-initialised. For class types, this means invoking the default constructor. That's what happens in your case for std::mutex
, so the initialisation m_()
can safely be omitted.
There's a difference when non-class types (int
, pointers, etc.) come into play. For these, default initialisation doesn't do anything (it leaves them with an indeterminate value), and so if you want such members initialised, you have to list them explicitly in the list. Even if listed just with ()
as the initialisation, this will turn it from default initialisation into value initialisation, which means initialising with a zero value for such types.
Upvotes: 4