为什么显式调用base move构造函数实际调用基类复制构造函数?

时间:2012-01-17 00:35:26

标签: c++ move-constructor

我试图通过派生类移动ctor显式调用基类移动ctor但是, surprise!,实际上调用基类复制ctor而不是基类移动ctor。

我在对象上使用std::move()函数以确保调用派生的移动ctor!

代码:

class Base
{
public:
    Base(const Base& rhs){ cout << "base copy ctor" << endl; }
    Base(Base&& rhs){ cout << "base move ctor" << endl; }
};

class Derived : public Base
{
public:

    Derived(Derived&& rhs) : Base(rhs) { cout << "derived move ctor"; }
    Derived(const Derived& rhs) : Base(rhs) { cout << "derived copy ctor" << endl; }
};

int main()
{
    Derived a;
    Derived y = std::move(a); // invoke move ctor
    cin.ignore();
    return 0;
}

计划输出:

  

base copy ctor

     

派生移动ctor

如你所见,基类移动ctor正在被遗忘,所以我该怎么称呼它?

3 个答案:

答案 0 :(得分:5)

Derived类的上下文中,参数rhs显然有一个名称。因此,它必须是左值,它不能是右值。但是,T&&仅绑定到右值。如果要调用基类的移动构造函数,则需要使用如下代码:

Derived(Derived&& rhs): Base(std::move(rhs)) { std::cout << "derived move ctor"; }

这将调用Base的移动构造函数并移动Base的{​​{1}}部分。由于rhsBase成员一无所知,Derived移动构造函数不会移动Base添加的任何内容。

答案 1 :(得分:2)

如果这两个条件都成立,编译器中只有&&的构造函数或任何其他函数或方法才有资格被编译器选中:

  • 您传入的表达式的数据类型为T&&T。 - 即不接受T&
  • 它实际上必须是一个右值 - 例如从函数返回(按值TT&&)。

move(rhs)满足这两个条件。 rhs属于正确的类型,但实际上必须从函数(例如move)返回,才能认为它有资格传递给需要&&的函数

答案 2 :(得分:1)

如果使用了基类移动构造函数,则派生的构造函数可以访问移动的对象。这很危险,所以除非你明确告诉编译器你已经完成了使用该对象并且移动是安全的,否则它不会发生。