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?
It's because there is constructor which can take an argument of int type. That temporary created object is copied to obj2 by invoking default copy-assignment. To avoid such conversions, mark constructor as explicit.
A constructor is called only once per object instance. Although, you may choose to call the constructor within the same class. You will have to call it with new key word. This will essentially create a new object instance and the constructor would be invoked by new instance.
And there are 4 calls to copy constructor in f function. 1) u is passed by value. 2) v is copy-initialized from u . 3) w is copy-initialized from v .
A copy constructor is called when a new object is created from an existing object, as a copy of the existing object. The assignment operator is called when an already initialized object is assigned a new value from another existing object.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With