Copy constructors are invoked in the following scenarios:
- When initializing one object of a class from another object (or reference) of the same class, the copy constructor is automatically called.
- When a function parameter is a class object passed by value, the copy constructor is called as the argument is copied into the parameter. (The compiler may optimize this away.)
- When a function returns a class object, the copy constructor is called. (Note: the compiler may optimize this, making the copy unobservable.)
#include<ctime>
#include<cstdlib>
#include<iterator>
#include<algorithm>
#include<iostream>
#include<numeric>
using namespace std;
class A {
public:
A():data(0){}
A(const A& a){
data = a.data;
cout << "copy constructor called\n";
}
A& operator=(const A&a){
data = a.data;
cout << "assignment operator called\n";
return *this;
}
int data;
};
void fun1(A a) {
return ;
}
A fun2() {
A a;
return a;
}
int main() {
A a;
A b(a); // initialize b from a — copy constructor
A c = a; // initialize c from a — this is initialization, not assignment
fun1(a); // pass by value — copies argument to parameter
A d = fun2(); // return by value — may be optimized away by the compiler
d = a; // d is already initialized — this is assignment, not copy construction
return 0;
}
Note on scenario 3 (returning a class object): the compiler typically applies copy elision to reduce unnecessary copies, so the actual behavior depends on the compiler and optimization flags. With g++, disabling optimization via g++ xxx.cpp -fno-elide-constructors produces:
copy constructor called
copy constructor called
copy constructor called
copy constructor called
copy constructor called
assignment operator called
With default optimization enabled:
copy constructor called
copy constructor called
copy constructor called
assignment operator called
The compiler’s optimization strategy: it first checks for copy elision; if that’s not supported, it looks for a move constructor; if neither is available, it falls back to the copy constructor. See move semantics and copy elision for more details.
Finally, note the difference between A c = a; (initialization — copy constructor) and d = a; (assignment — assignment operator).