Reputation: 1544
In the codebase on our project, I found something like this:
struct MeshData {
MeshData() {}
MeshData(MeshData&& obj) { *this = std::move(obj); }
MeshData& operator=(MeshData&& obj) {
if (this != &obj) {
indexes = std::move(obj.indexes);
}
return *this;
}
std::vector<int> indexes;
};
Implementing move construction in terms of the move assignment seems like a clever idea to me that reduces code duplication, but after looking for information I didn't find any especific advice regarding this.
My question is: Is this an antipattern or are there any situations where this shouldn't be done?
Upvotes: 3
Views: 1647
Reputation: 37488
One of the pitfalls of this approach can manifest itself when move constructors and move operators of member variables may yield different results. For example this would happen if indexes
was a vector
using custom allocator with std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value
evaluating to true
. In this case dedicated move constructor would move both allocator and data without throwing exceptions while calling move assignment would result in new storage being allocated and all the items move constructed leading to considerable overhead and preventing move constructor from being no throwing.
Upvotes: 3
Reputation: 65600
This cannot be done if your type has data members with no default constructors, and should not be done if they have default constructors which are expensive:
struct NoDefaultCtor {
NoDefaultCtor() = delete;
NoDefaultCtor(int){}
};
struct Foo {
Foo(Foo&& obj) { *this = std::move(obj); }
Foo& operator=(Foo&& obj) {
if (this != &obj) {
thing = std::move(obj.thing);
}
return *this;
}
NoDefaultCtor thing;
};
gives this error:
<source>: In constructor 'Foo::Foo(Foo&&)':
<source>:10:20: error: use of deleted function 'NoDefaultCtor::NoDefaultCtor()'
Foo(Foo&& obj) { *this = std::move(obj); }
^
<source>:5:5: note: declared here
NoDefaultCtor() = delete;
This is because all data members must be constructed before the body of the constructor is entered.
However, the best advice is to follow the Rule of Zero and avoid writing those special members at all.
Upvotes: 8