C++ copy constructor called at return The 2019 Stack Overflow Developer Survey Results Are...
Keeping a retro style to sci-fi spaceships?
How do PCB vias affect signal quality?
Can we generate random numbers using irrational numbers like π and e?
How to charge AirPods to keep battery healthy?
Why not take a picture of a closer black hole?
Can withdrawing asylum be illegal?
If I score a critical hit on an 18 or higher, what are my chances of getting a critical hit if I roll 3d20?
What do hard-Brexiteers want with respect to the Irish border?
Dynamic substitution of variables in bash
writing variables above the numbers in tikz picture
What is this business jet?
Why was M87 targeted for the Event Horizon Telescope instead of Sagittarius A*?
Can there be female White Walkers?
Why “相同意思的词” is called “同义词” instead of "同意词"?
Did Scotland spend $250,000 for the slogan "Welcome to Scotland"?
What could be the right powersource for 15 seconds lifespan disposable giant chainsaw?
Dropping list elements from nested list after evaluation
The difference between dialogue marks
APIPA and LAN Broadcast Domain
Can I have a signal generator on while it's not connected?
Getting crown tickets for Statue of Liberty
Correct punctuation for showing a character's confusion
Worn-tile Scrabble
Why can't devices on different VLANs, but on the same subnet, communicate?
C++ copy constructor called at return
The 2019 Stack Overflow Developer Survey Results Are InWhen to use virtual destructors?In which situations is the C++ copy constructor called?What are the differences between a pointer variable and a reference variable in C++?Why don't C++ compilers define operator== and operator!=?What is the lifetime of a static variable in a C++ function?Can I call a constructor from another constructor (do constructor chaining) in C++?Inheriting constructorsHow can I profile C++ code running on Linux?The Definitive C++ Book Guide and ListWhen to use virtual destructors?What is the “-->” operator in C++?What is the copy-and-swap idiom?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
error: use of deleted function 'A::A(const A&)'
return tmp;
^~~
Why is the copy constructor called only when there is a virtual destructor in A? How to avoid this?
struct B {};
struct A{
std::unique_ptr<B> x;
virtual ~A() = default;
};
A f() {
A tmp;
return tmp;
}
c++
add a comment |
error: use of deleted function 'A::A(const A&)'
return tmp;
^~~
Why is the copy constructor called only when there is a virtual destructor in A? How to avoid this?
struct B {};
struct A{
std::unique_ptr<B> x;
virtual ~A() = default;
};
A f() {
A tmp;
return tmp;
}
c++
1
see: In which situations is the C++ copy constructor called?
– kmdreko
Mar 21 at 20:29
5
C++ handles objects different than C#/Java. When an instance goes out of scope (tmphere) its destructor must be called. Therefore, when youreturn tmpthen you're asking it to make a copy oftmpto be return to whomever calls the function. Once copied,tmpwill be destroyed and its copy will be available for use.
– Everyone
Mar 21 at 20:29
3
@Everyone except that it is usually a move rather than a copy, which is what the question is about.
– Quentin
Mar 22 at 9:24
A little surprising as I would have thought that RVO would have been invoked, resulting in no move or copy.
– Adrian
Apr 1 at 19:53
add a comment |
error: use of deleted function 'A::A(const A&)'
return tmp;
^~~
Why is the copy constructor called only when there is a virtual destructor in A? How to avoid this?
struct B {};
struct A{
std::unique_ptr<B> x;
virtual ~A() = default;
};
A f() {
A tmp;
return tmp;
}
c++
error: use of deleted function 'A::A(const A&)'
return tmp;
^~~
Why is the copy constructor called only when there is a virtual destructor in A? How to avoid this?
struct B {};
struct A{
std::unique_ptr<B> x;
virtual ~A() = default;
};
A f() {
A tmp;
return tmp;
}
c++
c++
edited Mar 21 at 21:18
Sobuch
asked Mar 21 at 20:23
SobuchSobuch
936
936
1
see: In which situations is the C++ copy constructor called?
– kmdreko
Mar 21 at 20:29
5
C++ handles objects different than C#/Java. When an instance goes out of scope (tmphere) its destructor must be called. Therefore, when youreturn tmpthen you're asking it to make a copy oftmpto be return to whomever calls the function. Once copied,tmpwill be destroyed and its copy will be available for use.
– Everyone
Mar 21 at 20:29
3
@Everyone except that it is usually a move rather than a copy, which is what the question is about.
– Quentin
Mar 22 at 9:24
A little surprising as I would have thought that RVO would have been invoked, resulting in no move or copy.
– Adrian
Apr 1 at 19:53
add a comment |
1
see: In which situations is the C++ copy constructor called?
– kmdreko
Mar 21 at 20:29
5
C++ handles objects different than C#/Java. When an instance goes out of scope (tmphere) its destructor must be called. Therefore, when youreturn tmpthen you're asking it to make a copy oftmpto be return to whomever calls the function. Once copied,tmpwill be destroyed and its copy will be available for use.
– Everyone
Mar 21 at 20:29
3
@Everyone except that it is usually a move rather than a copy, which is what the question is about.
– Quentin
Mar 22 at 9:24
A little surprising as I would have thought that RVO would have been invoked, resulting in no move or copy.
– Adrian
Apr 1 at 19:53
1
1
see: In which situations is the C++ copy constructor called?
– kmdreko
Mar 21 at 20:29
see: In which situations is the C++ copy constructor called?
– kmdreko
Mar 21 at 20:29
5
5
C++ handles objects different than C#/Java. When an instance goes out of scope (
tmp here) its destructor must be called. Therefore, when you return tmp then you're asking it to make a copy of tmp to be return to whomever calls the function. Once copied, tmp will be destroyed and its copy will be available for use.– Everyone
Mar 21 at 20:29
C++ handles objects different than C#/Java. When an instance goes out of scope (
tmp here) its destructor must be called. Therefore, when you return tmp then you're asking it to make a copy of tmp to be return to whomever calls the function. Once copied, tmp will be destroyed and its copy will be available for use.– Everyone
Mar 21 at 20:29
3
3
@Everyone except that it is usually a move rather than a copy, which is what the question is about.
– Quentin
Mar 22 at 9:24
@Everyone except that it is usually a move rather than a copy, which is what the question is about.
– Quentin
Mar 22 at 9:24
A little surprising as I would have thought that RVO would have been invoked, resulting in no move or copy.
– Adrian
Apr 1 at 19:53
A little surprising as I would have thought that RVO would have been invoked, resulting in no move or copy.
– Adrian
Apr 1 at 19:53
add a comment |
1 Answer
1
active
oldest
votes
virtual ~A() = default; is a user declared destructor. Because of that, A no longer has a move constructor. That means return tmp; can't move tmp and since tmp is not copyable, you get a compiler error.
There are two ways you can fix this. You can add a move constructor like
struct A{
std::unique_ptr<B> x;
A() = default; // you have to add this since the move constructor was added
A(A&&) = default; // defaulted move
virtual ~A() = default;
};
or you can create a base class that has the virtual destructor and inherit from that like
struct C {
virtual ~C() = default;
};
struct A : C {
std::unique_ptr<B> x;
};
This works because A no longer has a user declared destructor (Yes, C does but we only care about A) so it will still generate a move constructor in A. The important part of this is that C doesn't have a deleted move constructor, it just doesn't have one period, so trying to move it will cause a copy. That means
C's copy constructor is called in A's implicitly generated move constructor since C(std::move(A_obj_to_move_from)) will copy as long as it doesn't have a deleted move constructor.
10
Better to follow the Rule of Zero/Five. Either add all of (copy ctor, move ctor, copy assignment, move assignment, destructor) or add none of them. In this example, none of them are necessary.
– 0x5453
Mar 21 at 20:33
3
@0x5453 Unless this is a parent class and the OP wants the derived classes to get destroyed properly. You need a virtual destructor if you have polymorphism.
– NathanOliver
Mar 21 at 20:34
3
@Tzalumen no delete is required (because that's what the unique pointer does for you), but a virtual destructor is required so that the unique pointer won't have UB.
– eerorika
Mar 21 at 20:40
3
@Tzalumen If youdeletean object of classXthrough a pointer to a base class ofXand that base class doesn't have a virtual dtor, it's Undefined Behaviour. Regardless of what the destructor does.
– Angew
Mar 21 at 20:41
3
@Tzalumen If you have polymorphism, you must have a virtual destructor. If you don't the destructor for the derived class won't be called and you have UB.
– NathanOliver
Mar 21 at 20:41
|
show 24 more comments
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55288708%2fc-copy-constructor-called-at-return%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
virtual ~A() = default; is a user declared destructor. Because of that, A no longer has a move constructor. That means return tmp; can't move tmp and since tmp is not copyable, you get a compiler error.
There are two ways you can fix this. You can add a move constructor like
struct A{
std::unique_ptr<B> x;
A() = default; // you have to add this since the move constructor was added
A(A&&) = default; // defaulted move
virtual ~A() = default;
};
or you can create a base class that has the virtual destructor and inherit from that like
struct C {
virtual ~C() = default;
};
struct A : C {
std::unique_ptr<B> x;
};
This works because A no longer has a user declared destructor (Yes, C does but we only care about A) so it will still generate a move constructor in A. The important part of this is that C doesn't have a deleted move constructor, it just doesn't have one period, so trying to move it will cause a copy. That means
C's copy constructor is called in A's implicitly generated move constructor since C(std::move(A_obj_to_move_from)) will copy as long as it doesn't have a deleted move constructor.
10
Better to follow the Rule of Zero/Five. Either add all of (copy ctor, move ctor, copy assignment, move assignment, destructor) or add none of them. In this example, none of them are necessary.
– 0x5453
Mar 21 at 20:33
3
@0x5453 Unless this is a parent class and the OP wants the derived classes to get destroyed properly. You need a virtual destructor if you have polymorphism.
– NathanOliver
Mar 21 at 20:34
3
@Tzalumen no delete is required (because that's what the unique pointer does for you), but a virtual destructor is required so that the unique pointer won't have UB.
– eerorika
Mar 21 at 20:40
3
@Tzalumen If youdeletean object of classXthrough a pointer to a base class ofXand that base class doesn't have a virtual dtor, it's Undefined Behaviour. Regardless of what the destructor does.
– Angew
Mar 21 at 20:41
3
@Tzalumen If you have polymorphism, you must have a virtual destructor. If you don't the destructor for the derived class won't be called and you have UB.
– NathanOliver
Mar 21 at 20:41
|
show 24 more comments
virtual ~A() = default; is a user declared destructor. Because of that, A no longer has a move constructor. That means return tmp; can't move tmp and since tmp is not copyable, you get a compiler error.
There are two ways you can fix this. You can add a move constructor like
struct A{
std::unique_ptr<B> x;
A() = default; // you have to add this since the move constructor was added
A(A&&) = default; // defaulted move
virtual ~A() = default;
};
or you can create a base class that has the virtual destructor and inherit from that like
struct C {
virtual ~C() = default;
};
struct A : C {
std::unique_ptr<B> x;
};
This works because A no longer has a user declared destructor (Yes, C does but we only care about A) so it will still generate a move constructor in A. The important part of this is that C doesn't have a deleted move constructor, it just doesn't have one period, so trying to move it will cause a copy. That means
C's copy constructor is called in A's implicitly generated move constructor since C(std::move(A_obj_to_move_from)) will copy as long as it doesn't have a deleted move constructor.
10
Better to follow the Rule of Zero/Five. Either add all of (copy ctor, move ctor, copy assignment, move assignment, destructor) or add none of them. In this example, none of them are necessary.
– 0x5453
Mar 21 at 20:33
3
@0x5453 Unless this is a parent class and the OP wants the derived classes to get destroyed properly. You need a virtual destructor if you have polymorphism.
– NathanOliver
Mar 21 at 20:34
3
@Tzalumen no delete is required (because that's what the unique pointer does for you), but a virtual destructor is required so that the unique pointer won't have UB.
– eerorika
Mar 21 at 20:40
3
@Tzalumen If youdeletean object of classXthrough a pointer to a base class ofXand that base class doesn't have a virtual dtor, it's Undefined Behaviour. Regardless of what the destructor does.
– Angew
Mar 21 at 20:41
3
@Tzalumen If you have polymorphism, you must have a virtual destructor. If you don't the destructor for the derived class won't be called and you have UB.
– NathanOliver
Mar 21 at 20:41
|
show 24 more comments
virtual ~A() = default; is a user declared destructor. Because of that, A no longer has a move constructor. That means return tmp; can't move tmp and since tmp is not copyable, you get a compiler error.
There are two ways you can fix this. You can add a move constructor like
struct A{
std::unique_ptr<B> x;
A() = default; // you have to add this since the move constructor was added
A(A&&) = default; // defaulted move
virtual ~A() = default;
};
or you can create a base class that has the virtual destructor and inherit from that like
struct C {
virtual ~C() = default;
};
struct A : C {
std::unique_ptr<B> x;
};
This works because A no longer has a user declared destructor (Yes, C does but we only care about A) so it will still generate a move constructor in A. The important part of this is that C doesn't have a deleted move constructor, it just doesn't have one period, so trying to move it will cause a copy. That means
C's copy constructor is called in A's implicitly generated move constructor since C(std::move(A_obj_to_move_from)) will copy as long as it doesn't have a deleted move constructor.
virtual ~A() = default; is a user declared destructor. Because of that, A no longer has a move constructor. That means return tmp; can't move tmp and since tmp is not copyable, you get a compiler error.
There are two ways you can fix this. You can add a move constructor like
struct A{
std::unique_ptr<B> x;
A() = default; // you have to add this since the move constructor was added
A(A&&) = default; // defaulted move
virtual ~A() = default;
};
or you can create a base class that has the virtual destructor and inherit from that like
struct C {
virtual ~C() = default;
};
struct A : C {
std::unique_ptr<B> x;
};
This works because A no longer has a user declared destructor (Yes, C does but we only care about A) so it will still generate a move constructor in A. The important part of this is that C doesn't have a deleted move constructor, it just doesn't have one period, so trying to move it will cause a copy. That means
C's copy constructor is called in A's implicitly generated move constructor since C(std::move(A_obj_to_move_from)) will copy as long as it doesn't have a deleted move constructor.
edited Mar 22 at 12:44
answered Mar 21 at 20:32
NathanOliverNathanOliver
98.6k16138218
98.6k16138218
10
Better to follow the Rule of Zero/Five. Either add all of (copy ctor, move ctor, copy assignment, move assignment, destructor) or add none of them. In this example, none of them are necessary.
– 0x5453
Mar 21 at 20:33
3
@0x5453 Unless this is a parent class and the OP wants the derived classes to get destroyed properly. You need a virtual destructor if you have polymorphism.
– NathanOliver
Mar 21 at 20:34
3
@Tzalumen no delete is required (because that's what the unique pointer does for you), but a virtual destructor is required so that the unique pointer won't have UB.
– eerorika
Mar 21 at 20:40
3
@Tzalumen If youdeletean object of classXthrough a pointer to a base class ofXand that base class doesn't have a virtual dtor, it's Undefined Behaviour. Regardless of what the destructor does.
– Angew
Mar 21 at 20:41
3
@Tzalumen If you have polymorphism, you must have a virtual destructor. If you don't the destructor for the derived class won't be called and you have UB.
– NathanOliver
Mar 21 at 20:41
|
show 24 more comments
10
Better to follow the Rule of Zero/Five. Either add all of (copy ctor, move ctor, copy assignment, move assignment, destructor) or add none of them. In this example, none of them are necessary.
– 0x5453
Mar 21 at 20:33
3
@0x5453 Unless this is a parent class and the OP wants the derived classes to get destroyed properly. You need a virtual destructor if you have polymorphism.
– NathanOliver
Mar 21 at 20:34
3
@Tzalumen no delete is required (because that's what the unique pointer does for you), but a virtual destructor is required so that the unique pointer won't have UB.
– eerorika
Mar 21 at 20:40
3
@Tzalumen If youdeletean object of classXthrough a pointer to a base class ofXand that base class doesn't have a virtual dtor, it's Undefined Behaviour. Regardless of what the destructor does.
– Angew
Mar 21 at 20:41
3
@Tzalumen If you have polymorphism, you must have a virtual destructor. If you don't the destructor for the derived class won't be called and you have UB.
– NathanOliver
Mar 21 at 20:41
10
10
Better to follow the Rule of Zero/Five. Either add all of (copy ctor, move ctor, copy assignment, move assignment, destructor) or add none of them. In this example, none of them are necessary.
– 0x5453
Mar 21 at 20:33
Better to follow the Rule of Zero/Five. Either add all of (copy ctor, move ctor, copy assignment, move assignment, destructor) or add none of them. In this example, none of them are necessary.
– 0x5453
Mar 21 at 20:33
3
3
@0x5453 Unless this is a parent class and the OP wants the derived classes to get destroyed properly. You need a virtual destructor if you have polymorphism.
– NathanOliver
Mar 21 at 20:34
@0x5453 Unless this is a parent class and the OP wants the derived classes to get destroyed properly. You need a virtual destructor if you have polymorphism.
– NathanOliver
Mar 21 at 20:34
3
3
@Tzalumen no delete is required (because that's what the unique pointer does for you), but a virtual destructor is required so that the unique pointer won't have UB.
– eerorika
Mar 21 at 20:40
@Tzalumen no delete is required (because that's what the unique pointer does for you), but a virtual destructor is required so that the unique pointer won't have UB.
– eerorika
Mar 21 at 20:40
3
3
@Tzalumen If you
delete an object of class X through a pointer to a base class of X and that base class doesn't have a virtual dtor, it's Undefined Behaviour. Regardless of what the destructor does.– Angew
Mar 21 at 20:41
@Tzalumen If you
delete an object of class X through a pointer to a base class of X and that base class doesn't have a virtual dtor, it's Undefined Behaviour. Regardless of what the destructor does.– Angew
Mar 21 at 20:41
3
3
@Tzalumen If you have polymorphism, you must have a virtual destructor. If you don't the destructor for the derived class won't be called and you have UB.
– NathanOliver
Mar 21 at 20:41
@Tzalumen If you have polymorphism, you must have a virtual destructor. If you don't the destructor for the derived class won't be called and you have UB.
– NathanOliver
Mar 21 at 20:41
|
show 24 more comments
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55288708%2fc-copy-constructor-called-at-return%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
1
see: In which situations is the C++ copy constructor called?
– kmdreko
Mar 21 at 20:29
5
C++ handles objects different than C#/Java. When an instance goes out of scope (
tmphere) its destructor must be called. Therefore, when youreturn tmpthen you're asking it to make a copy oftmpto be return to whomever calls the function. Once copied,tmpwill be destroyed and its copy will be available for use.– Everyone
Mar 21 at 20:29
3
@Everyone except that it is usually a move rather than a copy, which is what the question is about.
– Quentin
Mar 22 at 9:24
A little surprising as I would have thought that RVO would have been invoked, resulting in no move or copy.
– Adrian
Apr 1 at 19:53