Search code examples
c++c++11move-semanticsxvalue

Automatic xvalue optimization


Somewhat surprisingly (to me), the following two programs compile to different outputs, with the latter one having much better performance (tested with gcc and clang):

#include <vector>
int main()
{
    std::vector<int> a(2<<20);
    for(std::size_t i = 0; i != 1000; ++i) {
        std::vector<int> b(2<<20);
        a = b;
    }
}

vs.

#include <vector>
int main()
{
    std::vector<int> a(2<<20);
    for(std::size_t i = 0; i != 1000; ++i) {
        std::vector<int> b(2<<20);
        a = std::move(b);
    }
}

Could someone explain to me why the compiler does (or can) not automatically consider b an xvalue in the last assignment and apply move semantics without the explicit std::move cast?

Edit: Compiled with (g++|clang++) -std=c++11 -O3 -o test test.cpp


Solution

  • Compilers can't break the as-if rule

    As §1.9/1 states:

    The semantic descriptions in this International Standard define a parameterized nondeterministic abstract machine. This International Standard places no requirement on the structure of conforming implementations. In particular, they need not copy or emulate the structure of the abstract machine. Rather, conforming implementations are required to emulate (only) the observable behavior of the abstract machine as explained below

    i.e. a compiler can't change the observable behavior of the program. Automatically (even if with no repercussions) converting an assignment to a move assignment would break this statement.

    Copy elisions can slightly alter this behavior, but that is regulated by §12.8/31.

    If you want to use the move version, you'll have to explicitly ask for it as in the latter example.