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












17














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 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?










share|improve this question
























  • You wrote a move constructor but not a matching move assignment operator. Why not?
    – Jesper Juhl
    Dec 27 '18 at 15:06








  • 4




    std::move always work. In can't not work, it is a cast in disguise. The question is, why move constructor is not called - which is answered below.
    – SergeyA
    Dec 27 '18 at 15:11










  • @JesperJuhl Because move constructor is used here instead of move assignment. Move constructor is called when an object is initialized, like T a = std::move(b); or T a(std::move(b));, check en.cppreference.com/w/cpp/language/move_constructor for more details.
    – Searene
    Dec 27 '18 at 15:30
















17














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 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?










share|improve this question
























  • You wrote a move constructor but not a matching move assignment operator. Why not?
    – Jesper Juhl
    Dec 27 '18 at 15:06








  • 4




    std::move always work. In can't not work, it is a cast in disguise. The question is, why move constructor is not called - which is answered below.
    – SergeyA
    Dec 27 '18 at 15:11










  • @JesperJuhl Because move constructor is used here instead of move assignment. Move constructor is called when an object is initialized, like T a = std::move(b); or T a(std::move(b));, check en.cppreference.com/w/cpp/language/move_constructor for more details.
    – Searene
    Dec 27 '18 at 15:30














17












17








17


12





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 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?










share|improve this question















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 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?







c++






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 28 '18 at 0:43

























asked Dec 27 '18 at 14:52









Searene

6,6452380112




6,6452380112












  • You wrote a move constructor but not a matching move assignment operator. Why not?
    – Jesper Juhl
    Dec 27 '18 at 15:06








  • 4




    std::move always work. In can't not work, it is a cast in disguise. The question is, why move constructor is not called - which is answered below.
    – SergeyA
    Dec 27 '18 at 15:11










  • @JesperJuhl Because move constructor is used here instead of move assignment. Move constructor is called when an object is initialized, like T a = std::move(b); or T a(std::move(b));, check en.cppreference.com/w/cpp/language/move_constructor for more details.
    – Searene
    Dec 27 '18 at 15:30


















  • You wrote a move constructor but not a matching move assignment operator. Why not?
    – Jesper Juhl
    Dec 27 '18 at 15:06








  • 4




    std::move always work. In can't not work, it is a cast in disguise. The question is, why move constructor is not called - which is answered below.
    – SergeyA
    Dec 27 '18 at 15:11










  • @JesperJuhl Because move constructor is used here instead of move assignment. Move constructor is called when an object is initialized, like T a = std::move(b); or T a(std::move(b));, check en.cppreference.com/w/cpp/language/move_constructor for more details.
    – Searene
    Dec 27 '18 at 15:30
















You wrote a move constructor but not a matching move assignment operator. Why not?
– Jesper Juhl
Dec 27 '18 at 15:06






You wrote a move constructor but not a matching move assignment operator. Why not?
– Jesper Juhl
Dec 27 '18 at 15:06






4




4




std::move always work. In can't not work, it is a cast in disguise. The question is, why move constructor is not called - which is answered below.
– SergeyA
Dec 27 '18 at 15:11




std::move always work. In can't not work, it is a cast in disguise. The question is, why move constructor is not called - which is answered below.
– SergeyA
Dec 27 '18 at 15:11












@JesperJuhl Because move constructor is used here instead of move assignment. Move constructor is called when an object is initialized, like T a = std::move(b); or T a(std::move(b));, check en.cppreference.com/w/cpp/language/move_constructor for more details.
– Searene
Dec 27 '18 at 15:30




@JesperJuhl Because move constructor is used here instead of move assignment. Move constructor is called when an object is initialized, like T a = std::move(b); or T a(std::move(b));, check en.cppreference.com/w/cpp/language/move_constructor for more details.
– Searene
Dec 27 '18 at 15:30












1 Answer
1






active

oldest

votes


















38














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:



enter image description here






share|improve this answer

















  • 3




    Thank you for that table! Mind if I save and use intensively?
    – YSC
    Dec 27 '18 at 15:06










  • @YSC: I take no credit for the table, it was made by Howard Hinnant.
    – Vittorio Romeo
    Dec 27 '18 at 15:16






  • 7




    The slides from the host: accu.org/content/conf2014/Howard_Hinnant_Accu_2014.pdf
    – YSC
    Dec 27 '18 at 15:18






  • 8




    The easier to remember rule: =default or =delete or implement the 5 special member functions whenever you touch any of them.
    – Yakk - Adam Nevraumont
    Dec 27 '18 at 16:03











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53946915%2fstdmove-doesnt-work-when-the-derived-class-destructor-is-specified%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









38














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:



enter image description here






share|improve this answer

















  • 3




    Thank you for that table! Mind if I save and use intensively?
    – YSC
    Dec 27 '18 at 15:06










  • @YSC: I take no credit for the table, it was made by Howard Hinnant.
    – Vittorio Romeo
    Dec 27 '18 at 15:16






  • 7




    The slides from the host: accu.org/content/conf2014/Howard_Hinnant_Accu_2014.pdf
    – YSC
    Dec 27 '18 at 15:18






  • 8




    The easier to remember rule: =default or =delete or implement the 5 special member functions whenever you touch any of them.
    – Yakk - Adam Nevraumont
    Dec 27 '18 at 16:03
















38














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:



enter image description here






share|improve this answer

















  • 3




    Thank you for that table! Mind if I save and use intensively?
    – YSC
    Dec 27 '18 at 15:06










  • @YSC: I take no credit for the table, it was made by Howard Hinnant.
    – Vittorio Romeo
    Dec 27 '18 at 15:16






  • 7




    The slides from the host: accu.org/content/conf2014/Howard_Hinnant_Accu_2014.pdf
    – YSC
    Dec 27 '18 at 15:18






  • 8




    The easier to remember rule: =default or =delete or implement the 5 special member functions whenever you touch any of them.
    – Yakk - Adam Nevraumont
    Dec 27 '18 at 16:03














38












38








38






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:



enter image description here






share|improve this answer












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:



enter image description here







share|improve this answer












share|improve this answer



share|improve this answer










answered Dec 27 '18 at 14:53









Vittorio Romeo

57.4k17154293




57.4k17154293








  • 3




    Thank you for that table! Mind if I save and use intensively?
    – YSC
    Dec 27 '18 at 15:06










  • @YSC: I take no credit for the table, it was made by Howard Hinnant.
    – Vittorio Romeo
    Dec 27 '18 at 15:16






  • 7




    The slides from the host: accu.org/content/conf2014/Howard_Hinnant_Accu_2014.pdf
    – YSC
    Dec 27 '18 at 15:18






  • 8




    The easier to remember rule: =default or =delete or implement the 5 special member functions whenever you touch any of them.
    – Yakk - Adam Nevraumont
    Dec 27 '18 at 16:03














  • 3




    Thank you for that table! Mind if I save and use intensively?
    – YSC
    Dec 27 '18 at 15:06










  • @YSC: I take no credit for the table, it was made by Howard Hinnant.
    – Vittorio Romeo
    Dec 27 '18 at 15:16






  • 7




    The slides from the host: accu.org/content/conf2014/Howard_Hinnant_Accu_2014.pdf
    – YSC
    Dec 27 '18 at 15:18






  • 8




    The easier to remember rule: =default or =delete or implement the 5 special member functions whenever you touch any of them.
    – Yakk - Adam Nevraumont
    Dec 27 '18 at 16:03








3




3




Thank you for that table! Mind if I save and use intensively?
– YSC
Dec 27 '18 at 15:06




Thank you for that table! Mind if I save and use intensively?
– YSC
Dec 27 '18 at 15:06












@YSC: I take no credit for the table, it was made by Howard Hinnant.
– Vittorio Romeo
Dec 27 '18 at 15:16




@YSC: I take no credit for the table, it was made by Howard Hinnant.
– Vittorio Romeo
Dec 27 '18 at 15:16




7




7




The slides from the host: accu.org/content/conf2014/Howard_Hinnant_Accu_2014.pdf
– YSC
Dec 27 '18 at 15:18




The slides from the host: accu.org/content/conf2014/Howard_Hinnant_Accu_2014.pdf
– YSC
Dec 27 '18 at 15:18




8




8




The easier to remember rule: =default or =delete or implement the 5 special member functions whenever you touch any of them.
– Yakk - Adam Nevraumont
Dec 27 '18 at 16:03




The easier to remember rule: =default or =delete or implement the 5 special member functions whenever you touch any of them.
– Yakk - Adam Nevraumont
Dec 27 '18 at 16:03


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53946915%2fstdmove-doesnt-work-when-the-derived-class-destructor-is-specified%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

How to change which sound is reproduced for terminal bell?

Title Spacing in Bjornstrup Chapter, Removing Chapter Number From Contents

Can I use Tabulator js library in my java Spring + Thymeleaf project?