std::move doesn't work when the derived class' destructor is specified

  • A+
Category:Languages

I was trying to move an instance to another one, as follows:

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

Here is the output:

copy student 

As you can see, std::move didn't work, student was copied instead of moved, however, if I remove the undergraduate's destructor, i.e. the following line:

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

The output will become move student, which means std::move works. Why? Why didn't std::move work when the derived class' destructor is specified?

 


Specifying a class's destructor inhibits automatic generation of the move constructor and move assignment. You can restore them by using = 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 created an excellent table for his Everything You Ever Wanted To Know About Move Semantics (and then some)" presentation:

std::move doesn't work when the derived class' destructor is specified

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: