1

The source code :

#include <iostream>
#include <string>

using namespace std;

int counts = 0;

class A {
  public:
    A() {
      cout << ">> A(" << ++counts << ") constructor" << endl;
    }
    A(const A& a) {
      cout << ">> A(" << ++counts << ") copy constructor" << endl;
    }
    A& operator=(const A& a) {
      cout << ">> A(" << ++counts << ") = constructor" << endl;
      return *this;
    }
};

A get_A()
{
  A a1;
  cout << "address of a1 = " << &a1 << endl;
  return a1;
}

void test_1()
{
  A a2 = get_A();
  cout << "address of a2 = " << &a2 << endl;
}

int main()
{
  test_1();

  return 0;
}

The output :

>> A(1) constructor
address of a1 = 0x7fff5296daf8
address of a2 = 0x7fff5296daf8

My questions :

1. Why there is only one constructor invoked ? Should not the assignment constructor be invoked ?

2. Why the address of a1 and a2 are the same ?

Community
  • 1
  • 1
loverszhaokai
  • 127
  • 10
  • 1
    [RVO](https://en.wikipedia.org/wiki/Return_value_optimization) – jfly Jan 08 '16 at 08:43
  • it should be invoked the copy constructor.. you are creating an object from another object.. anyway the compiler will apply some optimisation to avoid those copies.. try to compile with `--fno-elide-constructors` – andrea.marangoni Jan 08 '16 at 08:44
  • `A a2 = get_A();` is not an assignment, it's an initialisation, and the assignment operator is not a constructor. If it weren't for optimisation, the copy constructor would be invoked. – molbdnilo Jan 08 '16 at 09:00

2 Answers2

3

The Return Value Optimisation (RVO) is a compiler optimisation which eliminates copying the temporary object that you create in get_a into test_1. This is why both objects have the same address - they are actually the exact same object. Your compiler is eliminating the redundant construct-and-copy, and just constructs the result in place.

ajshort
  • 3,684
  • 5
  • 29
  • 43
2
  1. Because of copy elision.
  2. Because of copy elision.

Instead of the return value of get_A() being used to copy-construct a2, the compiler just directly allocates the return value at the call site.

You can see the behaviour you expect if you turn off copy elision in your compiler (-fno-elide-constructors in GCC and Clang).

Community
  • 1
  • 1
TartanLlama
  • 63,752
  • 13
  • 157
  • 193
  • Is copy elision part of the compiler-optimization or part of the standard ? – Humam Helfawi Jan 08 '16 at 08:43
  • Copy elision is explicitly defined in the standard, as well at the circumstances where it can occur. – ajshort Jan 08 '16 at 08:44
  • It's defined in the standard but is optional, although I believe it may be made mandatory in C++17 to eliminate the necessity of a copy/move constructor in copy elision contexts. – TartanLlama Jan 08 '16 at 08:46
  • mmm I see, because I was wondering why it still working even I turend all optimization off in my compiler.. thanks – Humam Helfawi Jan 08 '16 at 08:46