Why is the copy constructor called twice in this code snippet?What are the rules for calling the superclass...
finding the number of complex number
Porting Linux to another platform requirements
Is my visa status for all destinations in a flight with connections checked in the beginning or before each flight?
A starship is travelling at 0.9c and collides with a small rock. Will it leave a clean hole through, or will more happen?
Is boss over stepping boundary/micromanaging?
How much mayhem could I cause as a sentient fish?
What is causing the chain skip after chain replacement?
How long is the D&D Starter Set campaign?
Why are these T-SQL jobs from different SQL Server instances executed on the same instance (AlwaysOn Availability Groups)
Is it a fallacy if someone claims they need an explanation for every word of your argument to the point where they don't understand common terms?
One Half of Ten; A Riddle
Early credit roll before the end of the film
Costs/Income from potential craftsmen
Traveling through the asteriod belt?
awk + sum all numbers
Why exactly do action photographers need high fps burst cameras?
Writing Cyrillic text to a file
What is the purpose of easy combat scenarios that don't need resource expenditure?
How do you funnel food off a cutting board?
Can we use the stored gravitational potential energy of a building to produce power?
Who is this Ant Woman character in this image alongside the Wasp?
Why did the villain in the first Men in Black movie care about Earth's Cockroaches?
A title for a history book
初めてです, is '初めて' an adverb?
Why is the copy constructor called twice in this code snippet?
What are the rules for calling the superclass constructor?Can I call a constructor from another constructor (do constructor chaining) in C++?C++ vector::push_back using default copy constructorWhy does r-value reference to object generator call require copy constructor?Why copy constructor is not called here?Copy constructor is not called when return by valueWhy this move constructor is so greedy?object as return value, no constructor called?Copy constructor not called when initializing an object with return value of a functionIs there any special reason why the move constructor is not elided in the snippet shown below?
I'm playing around with a few things to understand how copy constructors work. But I can't make sense of why the copy constructor is called twice for the creation of x2
. I would have assumed it would be called once when the return value of createX()
is copied into x2
.
I also looked at a few related questions on SO, but as far as I can tell I couldn't find the same simple scenario as I am asking here.
By the way, I'm compiling with -fno-elide-constructors
in order to see what's going on without optimizations.
#include <iostream>
struct X {
int i{2};
X() {
std::cout << "default constructor called" << std::endl;
}
X(const X& other) {
std::cout << "copy constructor called" << std::endl;
}
};
X createX() {
X x;
std::cout << "created x on the stack" << std::endl;
return x;
}
int main() {
X x1;
std::cout << "created x1" << std::endl;
std::cout << "x1: " << x1.i << std::endl << std::endl;
X x2 = createX();
std::cout << "created x2" << std::endl;
std::cout << "x2: " << x2.i << std::endl;
return 0;
}
This is the output:
default constructor called
created x1
x1: 2
default constructor called
created x on the stack
copy constructor called
copy constructor called
created x2
x2: 2
Can someone help me what I'm missing or overlooking here?
c++ c++14 copy-constructor
New contributor
add a comment |
I'm playing around with a few things to understand how copy constructors work. But I can't make sense of why the copy constructor is called twice for the creation of x2
. I would have assumed it would be called once when the return value of createX()
is copied into x2
.
I also looked at a few related questions on SO, but as far as I can tell I couldn't find the same simple scenario as I am asking here.
By the way, I'm compiling with -fno-elide-constructors
in order to see what's going on without optimizations.
#include <iostream>
struct X {
int i{2};
X() {
std::cout << "default constructor called" << std::endl;
}
X(const X& other) {
std::cout << "copy constructor called" << std::endl;
}
};
X createX() {
X x;
std::cout << "created x on the stack" << std::endl;
return x;
}
int main() {
X x1;
std::cout << "created x1" << std::endl;
std::cout << "x1: " << x1.i << std::endl << std::endl;
X x2 = createX();
std::cout << "created x2" << std::endl;
std::cout << "x2: " << x2.i << std::endl;
return 0;
}
This is the output:
default constructor called
created x1
x1: 2
default constructor called
created x on the stack
copy constructor called
copy constructor called
created x2
x2: 2
Can someone help me what I'm missing or overlooking here?
c++ c++14 copy-constructor
New contributor
add a comment |
I'm playing around with a few things to understand how copy constructors work. But I can't make sense of why the copy constructor is called twice for the creation of x2
. I would have assumed it would be called once when the return value of createX()
is copied into x2
.
I also looked at a few related questions on SO, but as far as I can tell I couldn't find the same simple scenario as I am asking here.
By the way, I'm compiling with -fno-elide-constructors
in order to see what's going on without optimizations.
#include <iostream>
struct X {
int i{2};
X() {
std::cout << "default constructor called" << std::endl;
}
X(const X& other) {
std::cout << "copy constructor called" << std::endl;
}
};
X createX() {
X x;
std::cout << "created x on the stack" << std::endl;
return x;
}
int main() {
X x1;
std::cout << "created x1" << std::endl;
std::cout << "x1: " << x1.i << std::endl << std::endl;
X x2 = createX();
std::cout << "created x2" << std::endl;
std::cout << "x2: " << x2.i << std::endl;
return 0;
}
This is the output:
default constructor called
created x1
x1: 2
default constructor called
created x on the stack
copy constructor called
copy constructor called
created x2
x2: 2
Can someone help me what I'm missing or overlooking here?
c++ c++14 copy-constructor
New contributor
I'm playing around with a few things to understand how copy constructors work. But I can't make sense of why the copy constructor is called twice for the creation of x2
. I would have assumed it would be called once when the return value of createX()
is copied into x2
.
I also looked at a few related questions on SO, but as far as I can tell I couldn't find the same simple scenario as I am asking here.
By the way, I'm compiling with -fno-elide-constructors
in order to see what's going on without optimizations.
#include <iostream>
struct X {
int i{2};
X() {
std::cout << "default constructor called" << std::endl;
}
X(const X& other) {
std::cout << "copy constructor called" << std::endl;
}
};
X createX() {
X x;
std::cout << "created x on the stack" << std::endl;
return x;
}
int main() {
X x1;
std::cout << "created x1" << std::endl;
std::cout << "x1: " << x1.i << std::endl << std::endl;
X x2 = createX();
std::cout << "created x2" << std::endl;
std::cout << "x2: " << x2.i << std::endl;
return 0;
}
This is the output:
default constructor called
created x1
x1: 2
default constructor called
created x on the stack
copy constructor called
copy constructor called
created x2
x2: 2
Can someone help me what I'm missing or overlooking here?
c++ c++14 copy-constructor
c++ c++14 copy-constructor
New contributor
New contributor
edited 2 hours ago
NathanOliver
93.7k16130198
93.7k16130198
New contributor
asked 3 hours ago
c_studentc_student
564
564
New contributor
New contributor
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
What you have to remember here is that the return value of a function is a distinct object. When you do
return x;
you copy initialize the return value object with x
. This is the first copy constructor call you see. Then
X x2 = createX();
uses the returned object to copy initialize x2
so that is the second copy you see.
One thing to note is that
return x;
will try to move x
into the return object if it can. Had you made a move constructor you would have seen this called. The reason for this is that since local objects go out of scope at the end of the function, the compiler treats the object as an rvalue and only if that does not find a valid overload does it fall back to returning it as an lvalue.
@FrançoisAndrieux Yeah. Updating the wording to make that more explicit that isn't something that is just allowed but has to be done.
– NathanOliver
2 hours ago
I'm not sure of the details of-fno-elide-constructors
but I'm assuming it prevents RVO.
– François Andrieux
2 hours ago
@FrançoisAndrieux It does not prevent guaranteed RVO if using C++17 since that is mandated that it has to happen, there isn't actually a temporary object created. See here where it only uses a single copy as the second one is mandated not to happen.
– NathanOliver
2 hours ago
So we have to assume OP is using a pre-C++17 standard?
– François Andrieux
2 hours ago
Kind of. The compiler they are using could have a bug, or they are using pre C++17. I'm inclined to believe it is the latter.
– NathanOliver
2 hours ago
|
show 1 more comment
First copy is in return of createX
X createX() {
X x;
std::cout << "created x on the stack" << std::endl;
return x; // First copy
}
Second one is to create x2 from the temporary return by createX.
X x2 = createX(); // Second copy
Notice that in C++17, second copy is forced to be elided.
add a comment |
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
});
}
});
c_student is a new contributor. Be nice, and check out our Code of Conduct.
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%2f54929274%2fwhy-is-the-copy-constructor-called-twice-in-this-code-snippet%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
What you have to remember here is that the return value of a function is a distinct object. When you do
return x;
you copy initialize the return value object with x
. This is the first copy constructor call you see. Then
X x2 = createX();
uses the returned object to copy initialize x2
so that is the second copy you see.
One thing to note is that
return x;
will try to move x
into the return object if it can. Had you made a move constructor you would have seen this called. The reason for this is that since local objects go out of scope at the end of the function, the compiler treats the object as an rvalue and only if that does not find a valid overload does it fall back to returning it as an lvalue.
@FrançoisAndrieux Yeah. Updating the wording to make that more explicit that isn't something that is just allowed but has to be done.
– NathanOliver
2 hours ago
I'm not sure of the details of-fno-elide-constructors
but I'm assuming it prevents RVO.
– François Andrieux
2 hours ago
@FrançoisAndrieux It does not prevent guaranteed RVO if using C++17 since that is mandated that it has to happen, there isn't actually a temporary object created. See here where it only uses a single copy as the second one is mandated not to happen.
– NathanOliver
2 hours ago
So we have to assume OP is using a pre-C++17 standard?
– François Andrieux
2 hours ago
Kind of. The compiler they are using could have a bug, or they are using pre C++17. I'm inclined to believe it is the latter.
– NathanOliver
2 hours ago
|
show 1 more comment
What you have to remember here is that the return value of a function is a distinct object. When you do
return x;
you copy initialize the return value object with x
. This is the first copy constructor call you see. Then
X x2 = createX();
uses the returned object to copy initialize x2
so that is the second copy you see.
One thing to note is that
return x;
will try to move x
into the return object if it can. Had you made a move constructor you would have seen this called. The reason for this is that since local objects go out of scope at the end of the function, the compiler treats the object as an rvalue and only if that does not find a valid overload does it fall back to returning it as an lvalue.
@FrançoisAndrieux Yeah. Updating the wording to make that more explicit that isn't something that is just allowed but has to be done.
– NathanOliver
2 hours ago
I'm not sure of the details of-fno-elide-constructors
but I'm assuming it prevents RVO.
– François Andrieux
2 hours ago
@FrançoisAndrieux It does not prevent guaranteed RVO if using C++17 since that is mandated that it has to happen, there isn't actually a temporary object created. See here where it only uses a single copy as the second one is mandated not to happen.
– NathanOliver
2 hours ago
So we have to assume OP is using a pre-C++17 standard?
– François Andrieux
2 hours ago
Kind of. The compiler they are using could have a bug, or they are using pre C++17. I'm inclined to believe it is the latter.
– NathanOliver
2 hours ago
|
show 1 more comment
What you have to remember here is that the return value of a function is a distinct object. When you do
return x;
you copy initialize the return value object with x
. This is the first copy constructor call you see. Then
X x2 = createX();
uses the returned object to copy initialize x2
so that is the second copy you see.
One thing to note is that
return x;
will try to move x
into the return object if it can. Had you made a move constructor you would have seen this called. The reason for this is that since local objects go out of scope at the end of the function, the compiler treats the object as an rvalue and only if that does not find a valid overload does it fall back to returning it as an lvalue.
What you have to remember here is that the return value of a function is a distinct object. When you do
return x;
you copy initialize the return value object with x
. This is the first copy constructor call you see. Then
X x2 = createX();
uses the returned object to copy initialize x2
so that is the second copy you see.
One thing to note is that
return x;
will try to move x
into the return object if it can. Had you made a move constructor you would have seen this called. The reason for this is that since local objects go out of scope at the end of the function, the compiler treats the object as an rvalue and only if that does not find a valid overload does it fall back to returning it as an lvalue.
edited 2 hours ago
answered 3 hours ago
NathanOliverNathanOliver
93.7k16130198
93.7k16130198
@FrançoisAndrieux Yeah. Updating the wording to make that more explicit that isn't something that is just allowed but has to be done.
– NathanOliver
2 hours ago
I'm not sure of the details of-fno-elide-constructors
but I'm assuming it prevents RVO.
– François Andrieux
2 hours ago
@FrançoisAndrieux It does not prevent guaranteed RVO if using C++17 since that is mandated that it has to happen, there isn't actually a temporary object created. See here where it only uses a single copy as the second one is mandated not to happen.
– NathanOliver
2 hours ago
So we have to assume OP is using a pre-C++17 standard?
– François Andrieux
2 hours ago
Kind of. The compiler they are using could have a bug, or they are using pre C++17. I'm inclined to believe it is the latter.
– NathanOliver
2 hours ago
|
show 1 more comment
@FrançoisAndrieux Yeah. Updating the wording to make that more explicit that isn't something that is just allowed but has to be done.
– NathanOliver
2 hours ago
I'm not sure of the details of-fno-elide-constructors
but I'm assuming it prevents RVO.
– François Andrieux
2 hours ago
@FrançoisAndrieux It does not prevent guaranteed RVO if using C++17 since that is mandated that it has to happen, there isn't actually a temporary object created. See here where it only uses a single copy as the second one is mandated not to happen.
– NathanOliver
2 hours ago
So we have to assume OP is using a pre-C++17 standard?
– François Andrieux
2 hours ago
Kind of. The compiler they are using could have a bug, or they are using pre C++17. I'm inclined to believe it is the latter.
– NathanOliver
2 hours ago
@FrançoisAndrieux Yeah. Updating the wording to make that more explicit that isn't something that is just allowed but has to be done.
– NathanOliver
2 hours ago
@FrançoisAndrieux Yeah. Updating the wording to make that more explicit that isn't something that is just allowed but has to be done.
– NathanOliver
2 hours ago
I'm not sure of the details of
-fno-elide-constructors
but I'm assuming it prevents RVO.– François Andrieux
2 hours ago
I'm not sure of the details of
-fno-elide-constructors
but I'm assuming it prevents RVO.– François Andrieux
2 hours ago
@FrançoisAndrieux It does not prevent guaranteed RVO if using C++17 since that is mandated that it has to happen, there isn't actually a temporary object created. See here where it only uses a single copy as the second one is mandated not to happen.
– NathanOliver
2 hours ago
@FrançoisAndrieux It does not prevent guaranteed RVO if using C++17 since that is mandated that it has to happen, there isn't actually a temporary object created. See here where it only uses a single copy as the second one is mandated not to happen.
– NathanOliver
2 hours ago
So we have to assume OP is using a pre-C++17 standard?
– François Andrieux
2 hours ago
So we have to assume OP is using a pre-C++17 standard?
– François Andrieux
2 hours ago
Kind of. The compiler they are using could have a bug, or they are using pre C++17. I'm inclined to believe it is the latter.
– NathanOliver
2 hours ago
Kind of. The compiler they are using could have a bug, or they are using pre C++17. I'm inclined to believe it is the latter.
– NathanOliver
2 hours ago
|
show 1 more comment
First copy is in return of createX
X createX() {
X x;
std::cout << "created x on the stack" << std::endl;
return x; // First copy
}
Second one is to create x2 from the temporary return by createX.
X x2 = createX(); // Second copy
Notice that in C++17, second copy is forced to be elided.
add a comment |
First copy is in return of createX
X createX() {
X x;
std::cout << "created x on the stack" << std::endl;
return x; // First copy
}
Second one is to create x2 from the temporary return by createX.
X x2 = createX(); // Second copy
Notice that in C++17, second copy is forced to be elided.
add a comment |
First copy is in return of createX
X createX() {
X x;
std::cout << "created x on the stack" << std::endl;
return x; // First copy
}
Second one is to create x2 from the temporary return by createX.
X x2 = createX(); // Second copy
Notice that in C++17, second copy is forced to be elided.
First copy is in return of createX
X createX() {
X x;
std::cout << "created x on the stack" << std::endl;
return x; // First copy
}
Second one is to create x2 from the temporary return by createX.
X x2 = createX(); // Second copy
Notice that in C++17, second copy is forced to be elided.
answered 3 hours ago
Jarod42Jarod42
117k12103186
117k12103186
add a comment |
add a comment |
c_student is a new contributor. Be nice, and check out our Code of Conduct.
c_student is a new contributor. Be nice, and check out our Code of Conduct.
c_student is a new contributor. Be nice, and check out our Code of Conduct.
c_student is a new contributor. Be nice, and check out our Code of Conduct.
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%2f54929274%2fwhy-is-the-copy-constructor-called-twice-in-this-code-snippet%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