2

I have a struct which stores an int:

struct foo {
    int value;

    foo(int value) : value(value) {
        std::cout << "value constr\n";
    }

    foo(foo const&) {
        std::cout << "copy constr\n";
    }

    foo(foo&&) {
        std::cout << "move constr\n";
    }
};

In the main method I do the following:

foo bar = foo(foo(foo(42)));

At that point I expect the usual constructor to be called at first and then move constructor several times because the argument will be an rvalue. However, the output is only "value constr".

Why neither copy nor move constructors are called and what actually happens in this example?

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
Artem Shalagin
  • 137
  • 1
  • 8

1 Answers1

3

Because of Copy elision, the appropriate constructor will be invoked to construct the object directly, copy/move constructors will be omitted. And since C++17 this behavior is guaranteed.

Under the following circumstances, the compilers are required to omit the copy- and move- constructors of class objects even if copy/move constructor and the destructor have observable side-effects:

  • In initialization, if the initializer expression is a prvalue and the cv-unqualified version of the source type is the same class as the class of the destination, the initializer expression is used to initialize the destination object:

    T x = T(T(T())); // only one call to default constructor of T, to initialize x
    
songyuanyao
  • 169,198
  • 16
  • 310
  • 405