概要
当类使用多重继承时,如何安全地设计移动构造函数?
细节
考虑以下场景:
struct T { };
struct U { };
struct X : public T, public U
{
X(X&& other)
: T(std::move(other))
, U(std::move(other)) // already moved?!
{
}
};
有没有办法既安全T又U安全地移动建造?
当类使用多重继承时,如何安全地设计移动构造函数?
考虑以下场景:
struct T { };
struct U { };
struct X : public T, public U
{
X(X&& other)
: T(std::move(other))
, U(std::move(other)) // already moved?!
{
}
};
有没有办法既安全T又U安全地移动建造?
tl;博士:问题中的代码没问题。
上面的代码很好,因为std::move它本身实际上并没有other以任何方式改变,它只是进行了一次强制转换以other形成一个右值引用,以便调用 and 的移动构造函数T而U不是它们的复制构造函数。
T(std::move(other))运行时,将T调用 的 move 构造函数(假设它有一个),并且Tinother将移动到Tin this。在运行之前,Uinother将被单独放置U(std::move(other))。
请注意,这意味着当您的移动构造函数代码X运行时,您不能依赖T和Uin的成员/成员函数other,因为这些位other已经被移动了。
作为旁注,它可以通过更改为来改进:
X(X&& other)
: T(std::move(static_cast<T&>(other)))
, U(std::move(static_cast<U&>(other)))
{
}
因为这个版本不依赖于X&&to T&&/的隐式向上转换U&&。依赖隐式向上转换可能是一个问题,因为T和/或U可能有一个T(X&&)构造函数或一个接受任何模板构造函数,它们中的任何一个都会被选中,而不是T(T&&)你真正想要调用的移动构造函数。
正如@je4d 的回答所解释的那样,问题中的代码很好。
你也可以这样写:
X(X&& other)
: T(static_cast<T&&>(other))
, U(static_cast<T&&>(other))
{
}
请参阅@jead 的答案评论以获取解释。
使用移动后,我可以在侧音构造函数主体中使用其他对象吗:
struct T { };
struct U { };
struct X : public T, public U
{
X(X&& other)
: T(std::move(other))
, U(std::move(other)) // already moved?!
{
member1 = other.member1; //something like.
}
};