I wrote a small script to test copy elision in C++:
#include<iostream>
using namespace std;
class Test{
public:
int m;
Test(int x = 0): m(x) { cout << "constructing!" << endl;}
Test(const Test& t): m(t.m) { cout << "copy constructing!" << endl;}
};
Test function_1(Test& t){
Test x;
cout << "testing_1" << endl;
return x;
}
Test function_2(Test t){
cout << "testing_2" << endl;
return t;
}
Test function_3(Test t){
cout << "testing_3" << endl;
return t;
}
int main(){
Test t(5);
cout << "main_1" << endl;
function_1(t);
cout << "main_2" << endl;
function_2(t);
cout << "main_3" << endl;
function_3(Test(6));
cout << "Done" << endl;
return 0;
}
This program prints (changing the C++ version from 11 to 14 to 17 didn't change the output by the way):
$ ./a
constructing!
main_1
constructing!
testing_1
main_2
copy constructing!
testing_2
copy constructing!
main_3
constructing!
testing_3
copy constructing!
Done
I'm having a tough time interpreting these results. It is unclear to me when and why the compiler would choose to call the copy constructor in some instances and not in others, especially in the context of classes being passed and returned as arguments to functions. When and why is the copy constructor called?