2

Class A defines all copy/move constructor/assignment as follows:

struct A 
{
    std::string s;

    A() : s("test") { }
    A(const A& other) : s(other.s) { std::cout << "Copy constructor\n";}
    A(A&& other) : s(std::move(other.s)) { std::cout << "Move constructor\n";}
    A& operator= (const A& other) { std::cout << "Copy assignment\n"; s = other.s; return *this;}
    A& operator= (A&& other) { std::cout << "Move assignment\n"; s = std::move(other.s); return *this;}
};

And the followings are functions returning an object of type A:

A f(A a) { return a; }
A g() { return A(); }

The main() function is this:

int main()
{
    A a1 = f(A());          // Move-construct
    A a2 = std::move(a1);   // Move-construct
    A a3 (std::move(a2));   // Move-construct
    A a4 (a1);              // Copy-construct
    A a5 = a4;              // Copy-construct
    a5 = f(A());            // Move constructor + Move assignment
    a5 = a4;                // Copy assignment
    a5 = g();               // Move assignment
    A a6 = g();             // None!! Member-wise assignment (?)
}

Can anybody tell me, why on earth none of the constructors and assignment operators is called for a6? Which part of C++11's documentation describes this behavior?

Kamiar
  • 164
  • 2
  • 14

2 Answers2

3

This is called copy elision and is described in C++ standard, section 12.8 pt 31.

When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object have side effects. In such cases, the implementation treats the source and target of the omitted copy/move operation as simply two different ways of referring to the same object (...)

The circumstances are described as well. One of which being:

when a temporary class object that has not been bound to a reference would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move

As g() returns a temporary anonymous object (not bound to a reference), is is constructed directly into the target a6. In your example, the default constructor of g's return statement is used.

Christophe
  • 68,716
  • 7
  • 72
  • 138
1

With http://en.wikipedia.org/wiki/Return_value_optimization in A a6 = g();, the code within g creates a6 by calling one of the A constructors somewhere in the middle of the body of g.

pts
  • 80,836
  • 20
  • 110
  • 183