2
#include <iostream>
using namespace std;

class A {
public:
    A() {
        cout << "A()" << endl;
    }
    A(const A& a) {
        cout << "A(const A& a)" << endl;
    }
    A(A&& a) {
        cout << "A(A&& a)" << endl;
    }
    A& operator=(const A& a) {
        cout << "operator=(const A& a)" << endl;
        return *this;
    }
    A& operator=(A&& a) {
        cout << "operator=(A&& a)" << endl;
        return *this;
    }
    ~A() {
        cout << "~A()" << endl;
    };
};

A foo() {
    A a;
    return a;
}

int main() {
    A a = foo();
}

Compile:

clang++ test.cpp -o test -std=c++11

Output:

A()
~A()

Why there is just one pair of A() and ~A() in the output?

Why the move constructor is not called?

Have the compiler done some code optimization?

chaosink
  • 1,329
  • 13
  • 27

1 Answers1

6

Move (or copy) constructor is not called because of Copy Elision. Compiler constructed local variable in the return value place directly.

Such optimizations are also referred to as RVO (Return Value Optimization).

There are certain conditions for the compiler to allow such optimizations and they are mentioned in Standard. But it may more convenient to quote Item 25 of Effective Modern C++ by Scott Meyers regarding these conditions (not so rigorous information as in Standard, but maybe more efficient to absorb):

Paraphrasing the legalistic (arguably toxic) prose of the Standard, [...] compilers may elide the copying (or moving) of a local object in a function that returns by value if (1) the type of the local object is the same as that returned by the function and (2) the local object is what’s being returned.

k.v.
  • 1,193
  • 8
  • 11