C++ 标准::移动不';当派生类';已指定析构函数

C++ 标准::移动不';当派生类';已指定析构函数,c++,C++,我试图将一个实例移动到另一个实例,如下所示: #include <iostream> class student { public: student() = default; student(const student& student) { std::cout << "copy student" << std::endl; } student(student&& student) {

我试图将一个实例移动到另一个实例,如下所示:

#include <iostream>

class student {
public:
    student() = default;
    student(const student& student) {
        std::cout << "copy student" << std::endl;
    }
    student(student&& student) {
        std::cout << "move student" << std::endl;
    }
    virtual ~student() = default;
};

class undergraduate: public student {
public:
    undergraduate(): student() {}
    ~undergraduate() override = default; // removing this line will make std::move work
};

int main() {
    undergraduate student;
    undergraduate student1 = std::move(student);
}
如您所见,
std::move
不起作用,
student
被复制而不是移动,但是,如果我删除
本科生的析构函数,即以下行:

~undergraduate() override = default; // removing this line will make std::move work

输出将变成
move student
,这意味着
std::move
可以工作。为什么?指定派生类的析构函数时,
std::move
为什么不起作用?

指定类的析构函数会禁止自动生成移动构造函数和移动赋值。您可以使用
=default
还原它们:

class undergraduate: public student {
public:
    undergraduate(): student() {}
    ~undergraduate() override = default;

    undergraduate(const undergraduate&) = default;
    undergraduate& operator=(const undergraduate&) = default;

    undergraduate(undergraduate&&) = default;
    undergraduate& operator=(undergraduate&&) = default;
};
Howard Hinnant创建了一个优秀的表格,提供了您想要了解的关于移动语义的所有信息(以及一些)“演示:


谢谢你的表格!介意我集中保存和使用吗?@YSC:我不相信这张表格,它是由Howard Hinnant制作的。主持人的幻灯片:更容易记住的规则:
=default
=delete
,或者在你触摸其中任何一个时实现5个特殊成员函数。你编写了移动构造函数,但没有一个匹配的移动赋值运算符。为什么不?
std::move
总是起作用。在“不能起作用”中,这是一个伪装。问题是,为什么不调用移动构造函数?下面回答了这个问题。@JesperJuhl,因为这里使用的是移动构造函数而不是移动赋值。在初始化对象时调用移动构造函数,如
 T a=std::move(b);
T a(std::move(b));
,查看更多详细信息。
class undergraduate: public student {
public:
    undergraduate(): student() {}
    ~undergraduate() override = default;

    undergraduate(const undergraduate&) = default;
    undergraduate& operator=(const undergraduate&) = default;

    undergraduate(undergraduate&&) = default;
    undergraduate& operator=(undergraduate&&) = default;
};