Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copy constructor call for temporary object

Tags:

c++

I have a following code:

#include <iostream>
using namespace std;
struct A
{
    A() {}
    A(const A&)  { cout << "copy const" << endl; }
    A(A&)  { cout << "copy non const" << endl; }
};
A f(A a)
{
    return a;
}
int main() {
  A a1 = f(A());
}

The A(A&) copy constructor is called. Why A(const A&) is not called since I pass a temporary object? When I comment out the A(const A&) copy constructor the program does not compile.

like image 683
michalt38 Avatar asked Jan 25 '23 09:01

michalt38


1 Answers

What you are seeing is a mix of copy elision and an actual copy being made. Since f takes a by value, It needs to copy A() into a. The compiler sees this copy really isn't needed, so it elides that and instead directly constructs a so you don't see any call. In the body of f when you return a;, it needs to copy a into the return value. Since a is a lvalue, A(A&) is a better match than A(const A&) so you see the call to the non const copy constructor. Then a1 needs to be initialized from f's return value. Again copy elision comes into play again and instead of seeing a copy it just directly puts the return value into a1's storage.

So, elide, non-const copy, elide, which leaves the output with just copy non const


You get an error when you remove A(const A&) because even though those copies were elided, C++ still required there to be copy constructor until C++17.


If you compile with gcc or clang and use -fno-elide-constructors you can actually see those copies. You can see that in this live example. Note that I used -std=c++11 to turn off C++17's guaranteed copy elision

like image 165
NathanOliver Avatar answered Feb 05 '23 02:02

NathanOliver