4

I have some confusion on initializing objects through direct initialization passing temporary objects..

Here is the code I want to understand:

class Foo {
    public:
        Foo() { cout << "ctor()\n"; }
        Foo(int) { cout << "ctor(int)\n"; }
        Foo(const Foo&) { cout << "cpy-ctor\n"; }
        Foo& operator=(const Foo&) { cout << "copy-assignment\n"; return *this; }
};


int main() {

    Foo();// ctor (temporary object). it is not a function prototype because it requires a return type.
    cout << endl;

    Foo f; // ctor()
    cout << endl;

    Foo f2(Foo(7)); // ctor only once
    cout << endl;

    Foo f3(Foo(Foo(7))); // ctor(int), cpy-ctor() only once
    cout << endl;

    Foo f4(Foo(Foo(Foo(7)))); // ctor(int), cpy-ctor() only once
    cout << endl;

    Foo f5(Foo(Foo(Foo(Foo(7))))); // ctor(int), cpy-ctor(), cpy-ctor
    cout << endl;
}
  • As you can see above, in the first call it is OK. It creates an rvalue object calling the default constructor. Because it doesn't provide a return type the compiler easily treats it as an object declaration. Foo();.

Nothing new in the second call Foo f; which is invoking the default ctor.

  • I'm confused by the third call: Foo(Foo(7)) I thought the compiler would create a temporary object then pass it to the copy constructor to construct object f2 but it only calls the one-argument constructor Foo(int).

Does this mean that the compiler applies some optimization to remove the unnecessary copies?

  • Now in Foo f3(Foo(Foo(7))); it calls ctor and cpy-ctor but why? The same for f4, though it is different?

  • Finally Foo f5(Foo(Foo(Foo(Foo(7))))); invokes the ctor once and the cpy-ctor twice only?

I want to know what is happening exactly, also I tried the same code with no optimization and different levels of it but the result is the same. Thank you.

Boann
  • 48,794
  • 16
  • 117
  • 146
AdamMenz
  • 381
  • 1
  • 13
  • 7
    It's all detailed [here](https://en.cppreference.com/w/cpp/language/copy_elision). – François Andrieux Feb 08 '19 at 20:27
  • 3
    Copy elision... – Jesper Juhl Feb 08 '19 at 20:27
  • @FrançoisAndrieux: Thank you for the link. – AdamMenz Feb 08 '19 at 20:29
  • @JesperJuhl: Thank you. – AdamMenz Feb 08 '19 at 20:30
  • 1
    The canonical dupe: [What are copy elision and return value optimization?](https://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization) Plenty more of information. I'm not dupe-hammering in case someone can write up a better-targeted answer. – user4581301 Feb 08 '19 at 20:42
  • 1
    None of the compiler I tested called the copy constructor with c++17 standard. Previous to c++17 some compiler did not implemented copy elision: it was not mandatory. In c++17 `Foo(....(Foo(7))` is an expression (a pure rvalue expression) not an object. This expression is equivalent to `Foo(7)`. – Oliv Feb 08 '19 at 20:47

0 Answers0