Search code examples
c++c++17movereturn-value-optimization

C++17 copy elision rules and implicitly move


There is the following piece of code

#include <iostream>

class A {
public:
    A() {}

    // Explicit move constructor
     A(A&&) noexcept {
        std::cout << "move ctor" << std::endl;
    }

    // Copy constructor is deleted
    A(const A&) = delete;

    char x;
};
A a;
A foo() {
    A a;
    return a;  // Return by value, let the compiler apply move semantics
}
A bar() {
    
    return a;  // Return by value, let the compiler apply move semantics
}
int main() {
    A a = foo();  // Explicit move of the returned object
    A a2 = bar();
}

using the following arguments for compilation --std=c++17 -fno-elide-constructors example Inside foo since copy elision is disabled based on standard if x is move-eligible, the expression x is an rvalue. Otherwise, it is an lvalue.

Based on this the move constructor is called .

For the bar the return value is a which has static storage. For this, the move constructor is not implicitly called . It is needed explicity use move. My question is why this difference based on if storage of variable a?


Solution

  • My question is why this difference based on if storage of variable a?

    Because it would be fatal if simply writing return a; in a function meant that a's state will be lost next time it is used. Imagine you have

    std::vector<int> x;
    std::vector<int> f() { return x; }
    

    would then want that x will become empty each time f is called?

    The only reason that it makes sense to automatically move local variables with automatic storage duration is that we know that they can't be used anymore once the function exits.