Reputation: 15284
I did search the internet and found 3 ways of defining a move constructor:
Relying on compiler:
T(T&& other) = default;
Dereference this
pointer:
T(T&& other) {
*this = std::move(other);
}
Explicitly reassign all members:
T(T&& other) {
T.a = other.a;
T.b = other.b;
//...
}
Which one is the proper way ? (And is the second one even correct?)
Upvotes: 11
Views: 770
Reputation: 477020
The proper generic way is to move-construct each member, but that's what the defauted version does anyway:
T(T && rhs)
: a(std::move(rhs.a))
, b(std::move(rhs.b))
{ }
As a rough rule, you should use the default definition if this is all you need, and you should write an explicit move constructor if you're doing something that explicitly implements move semantics, such as a unique-ownership resource manager:
URM(URM && rhs)
: resource(rhs.resource)
{
rhs.resource = nullptr;
}
The indicator for whether this is appropriate is probably whether your class has a user-defined destructor. In the example, the destructor would release the managed resource, and this must happen only once, so the moved-from object must be modified.
This is unrelated, but since you are mentioning the assignment operator, here's the popular swap-and-assign/swap idiom:
void swap(URM & rhs) noexcept // assume members are noexcept-swappable!
{
using std::swap;
swap(resource, rhs.resource);
// ...
}
URM & operator=(URM rhs) noexcept // pass by value
{
rhs.swap(*this);
return *this;
}
The beauty of this approach is that you only need one single version of the assignment operator that works for temporaries and non-temporaries alike, using move construction when appropriate, and as long as all your members are well-designed, you also only need one single swap
function. On top of that, if the swap function doesn't throw (which a well-designed class should allow), then your assignment operator doesn't throw, since all the possible exceptions would already occur at the call site.
Upvotes: 18
Reputation:
T(T&& other)
: data(0) // initialize members
{
swap(other); // where the class has a member function swap or std::swap(this->data, other.data)
}
Upvotes: 1