RVO, move semantics and the struggle towards optimal code

248 views Asked by At

If I get it correctly, move semantics allows to move and reuse resources from temporary, unnamed objects. RVO, albeit preceding move semantics goes further and "steals" the entire object to avoid the extra constructor call and assignment/copy function.

This seems a bit counter intuitive to me, wouldn't it be that much faster, simple and user obvious if the called constructor uses directly the address of the final lvalue target to directly emplace data where the user needs it?

I mean, "create this object in this location" seems a bit more intuitive than "create this object somewhere, then copy it to its right location".

1

There are 1 answers

0
AudioBubble On

Yes it is "a bit counter intuitive". With copy elision enabled all side effects of the constructor are elided, too.

#include <iostream>

struct X {
    X() { std::cout << "Construct" << std::endl; }
    X(X&&) { std::cout << "Move" << std::endl; }
    ~X() { std::cout << "Destruct" << std::endl; };
};

X f() { return X(); }

int main()
{
    X x(f());
    return 0;
}

Copy elision: g++ -std=c++11 src-test/main.cc

Construct
Destruct

No copy elision: g++ -std=c++11 -fno-elide-constructors src-test/main.cc

Construct
Move
Destruct
Move
Destruct
Destruct

The compiler, knowing the hardware the program/library is build for, is able to apply (optional) copy elision. The C++ language, itself, is not aware of hardware specific return mechanisms. Hence it is not possible to construct at a certain address in this context.