I know of the following situations in c++ where the copy constructor would be invoked:
when an existing object is assigned an object of it own class
MyClass A,B;
A = new MyClass();
B=A; //copy constructor called
if a functions receives as argument, passed by value, an object of a class
void foo(MyClass a);
foo(a); //copy constructor invoked
when a function returns (by value) an object of the class
MyClass foo ()
{
MyClass temp;
....
return temp; //copy constructor called
}
Please feel free to correct any mistakes I've made; but I am more curious if there are any other situations in which the copy constructor is called.
A constructor in C++ is a special method that is automatically called when an object of a class is created.
The copy constructor is a type of constructor. It creates an object and initializes it with an object of the same class. If the copy constructor is not defined in the class, the compiler itself defines one. A copy constructor is a must for a class that has pointer variables or dynamic memory allocations.
The reason the copy constructor is not called is because the copy constructor itself is a function with one parameter.
A copy constructor defines what copying means,So if we pass an object only (we will be passing the copy of that object) but to create the copy we will need a copy constructor, Hence it leads to infinite recursion. So, A copy constructor must have a reference as an argument.
When an existing object is assigned an object of it own class
B = A;
Not necessarily. This kind of assignment is called copy-assignment, meaning the assignment operator of the class will be called to perform memberwise assignment of all the data members. The actual function is MyClass& operator=(MyClass const&)
The copy-constructor is not invoked here. This is because the assignment operator takes a reference to its object, and therefore no copy-construction is performed.
Copy-assignment is different from copy-initialization because copy-initialization is only done when an object is being initialized. For example:
T y = x;
x = y;
The first expression initializes y
by copying x
. It invokes the copy-constructor MyClass(MyClass const&)
.
And as mentioned, x = y
is a call to the assignment operator.
(There is also something called copy-elison whereby the compiler will elide calls to the copy-constructor. Your compiler more than likely uses this).
If a functions receives as argument, passed by value, an object of a class
void foo(MyClass a); foo(a);
This is correct. However, note that in C++11 if a
is an xvalue and if MyClass
has the appropriate constructor MyClass(MyClass&&)
, a
can be moved into the parameter.
(The copy-constructor and the move-constructor are two of the default compiler-generated member functions of a class. If you do not supply them yourself, the compiler will generously do so for you under specific circumstances).
When a function returns (by value) an object of the class
MyClass foo () { MyClass temp; .... return temp; // copy constructor called }
Through return-value optimization, as mentioned in some of the answers, the compiler can remove the call to the copy-constructor. By using the compiler option -fno-elide-constructors
, you can disable copy-elison and see that the copy-constructor would indeed be called in these situations.
I might be wrong about this, but this class allows you to see what is called and when:
class a {
public:
a() {
printf("constructor called\n");
};
a(const a& other) {
printf("copy constructor called\n");
};
a& operator=(const a& other) {
printf("copy assignment operator called\n");
return *this;
};
};
So then this code:
a b; //constructor
a c; //constructor
b = c; //copy assignment
c = a(b); //copy constructor, then copy assignment
produces this as the result:
constructor called
constructor called
copy assignment operator called
copy constructor called
copy assignment operator called
Another interesting thing, say you have the following code:
a* b = new a(); //constructor called
a* c; //nothing is called
c = b; //still nothing is called
c = new a(*b); //copy constructor is called
This occurs because when you when you assign a pointer, that does nothing to the actual object.
Situation (1) is incorrect and does not compile the way you've written it. It should be:
MyClass A, B;
A = MyClass(); /* Redefinition of `A`; perfectly legal though superfluous: I've
dropped the `new` to defeat compiler error.*/
B = A; // Assignment operator called (`B` is already constructed)
MyClass C = B; // Copy constructor called.
You are correct in case (2).
But in case (3), the copy constructor may not be called: if the compiler can detect no side effects then it can implement return value optimisation to optimise out the unnecessary deep copy. C++11 formalises this with rvalue references.
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