这取决于继承层次结构。但是很有可能这段代码很好。这是一个完整的演示,表明它是安全的(对于这个特定的演示):
#include <iostream>
struct base1
{
base1() = default;
base1(base1&&) {std::cout << "base1(base1&&)\n";}
};
struct base2
{
base2() = default;
base2(base2&&) {std::cout << "base2(base2&&)\n";}
};
struct br1
{
br1() = default;
br1(br1&&) {std::cout << "br1(br1&&)\n";}
};
struct br2
{
br2() = default;
br2(br2&&) {std::cout << "br2(br2&&)\n";}
};
struct X
: public base1
, public base2
{
br1 mbr1;
br2 mbr2;
public:
X() = default;
X(X&& rhs)
: base1(std::move(rhs))
, base2(std::move(rhs))
, mbr1(std::move(rhs.mbr1))
, mbr2(std::move(rhs.mbr2))
{ }
};
int
main()
{
X x1;
X x2 = std::move(x1);
}
应该输出:
base1(base1&&)
base2(base2&&)
br1(br1&&)
br2(br2&&)
在这里您可以看到每个基地和每个成员都只移动了一次。
记住:std::move 并没有真正移动。它只是一个右值转换,仅此而已。
因此代码转换为右值X,然后将其传递给基类。假设基类看起来像我上面概述的那样,那么有一个隐式转换为右值 base1 和 base2,这将移动构造这两个单独的基类。
还有,
记住:移出的对象处于有效但未指定的状态。
只要base1 和base2 的移动构造函数没有进入派生类并更改mbr1 或mbr2,那么这些成员仍处于已知状态并准备移动从。没问题。
现在我确实提到了可能会出现问题。方法如下:
#include <iostream>
struct base1
{
base1() = default;
base1(base1&& b)
{std::cout << "base1(base1&&)\n";}
template <class T>
base1(T&& t)
{std::cout << "move from X\n";}
};
struct base2
{
base2() = default;
base2(base2&& b)
{std::cout << "base2(base2&&)\n";}
};
struct br1
{
br1() = default;
br1(br1&&) {std::cout << "br1(br1&&)\n";}
};
struct br2
{
br2() = default;
br2(br2&&) {std::cout << "br2(br2&&)\n";}
};
struct X
: public base1
, public base2
{
br1 mbr1;
br2 mbr2;
public:
X() = default;
X(X&& rhs)
: base1(std::move(rhs))
, base2(std::move(rhs))
, mbr1(std::move(rhs.mbr1))
, mbr2(std::move(rhs.mbr2))
{ }
};
int
main()
{
X x1;
X x2 = std::move(x1);
}
在这个例子中,base1 有一个模板化的构造函数,它接受一个右值的东西。如果这个构造函数可以绑定到右值X,并且如果这个构造函数会从右值X移动,那么你就有问题了:
move from X
base2(base2&&)
br1(br1&&)
br2(br2&&)
解决此问题的方法(相对罕见,但并非非常罕见)是forward<base1>(rhs) 而不是move(rhs):
X(X&& rhs)
: base1(std::forward<base1>(rhs))
, base2(std::move(rhs))
, mbr1(std::move(rhs.mbr1))
, mbr2(std::move(rhs.mbr2))
{ }
现在base1 看到的是右值base1 而不是右值X,这将绑定到base1 移动构造函数(假设它存在),所以你再次得到:
base1(base1&&)
base2(base2&&)
br1(br1&&)
br2(br2&&)
世界再好不过了。