概要
当类使用多重继承时,如何安全地设计移动构造函数?
细节
考虑以下场景:
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 构造函数(假设它有一个),并且T
inother
将移动到T
in this
。在运行之前,U
inother
将被单独放置U(std::move(other))
。
请注意,这意味着当您的移动构造函数代码X
运行时,您不能依赖T
和U
in的成员/成员函数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.
}
};