std :: move не работает, когда указан деструктор производного класса

Я пытался переместить экземпляр на другой, как показано ниже:

#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);
}

Вот вывод:

copy student

Как вы можете видеть, std::move не работал, student был скопирован вместо перемещения, однако, если я удалю деструктор undergraduate, то есть следующую строку:

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

Выходными данными станет move student, что означает, что работает std::move. Зачем? Почему std::move работает, когда указан деструктор производного класса?

Ответ 1

Указание деструктора класса запрещает автоматическую генерацию конструктора перемещения и назначения перемещения. Вы можете восстановить их, используя = 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;
};

Говард Хиннант создал отличную таблицу для своей презентации "Все, что вы когда-либо хотели знать о семантике перемещения (а затем и о некоторых)":

enter image description here