问题
Synopsis
How can I safely design a move constructor when a class uses multiple inheritance?
Details
Consider the following scenario:
struct T { };
struct U { };
struct X : public T, public U
{
X(X&& other)
: T(std::move(other))
, U(std::move(other)) // already moved?!
{
}
};
Is there a way to move-construct both T
and U
safely?
回答1:
tl;dr: the code in the question is ok.
The code above is fine, because std::move
itself doesn't actually change other
in any way, it just does a cast to make other
into an rvalue reference so that the move constructors of T
and U
are called instead of their copy constructors.
When T(std::move(other))
is run, T
's move constructor will be called (assuming it has one) and the T
in other
will be moved to the T
in this
. The U
in other
will be left alone until the U(std::move(other))
is run.
Note that this means that when your move constructor code for X
runs, you cannot rely on the members/member functions of T
and U
in other
, as those bits of other
will have already have been moved.
As a side note, it could be improved by being changed to:
X(X&& other)
: T(std::move(static_cast<T&>(other)))
, U(std::move(static_cast<U&>(other)))
{
}
because this version doesn't rely on the implicit upcast from X&&
to T&&
/U&&
. Relying on the implicit upcast can be a problem because T
and/or U
may have a T(X&&)
constructor or an accept-anything template constructor, either of which would get picked instead of the T(T&&)
move constructor that you really want to call.
来源:https://stackoverflow.com/questions/10114701/move-constructors-and-multiple-inheritance