Cast to rvalue reference prevents copy elision

81 Views Asked by At

I read more related articles, but none of the answers clarified my doubts. Why in the code below the optimization takes place only when there is no cast to an rvalue reference, otherwise either the move (whether provided) or the copy (if there is no move constructor provided) constructor is called.

struct Clasa{
    Clasa(){
        std::cout << "Default" << std::endl;
    }
    Clasa(const Clasa& clasa){
        std::cout << "Copy" << std::endl;
    }
    Clasa(Clasa&& clasa){
        std::cout << "Move" << std::endl;
    }
    ~Clasa(){
        std::cout << "Destructor" << std::endl;
    }
};

int main(){
    Clasa c = (Clasa&&)Clasa();//no optimization
    Clasa d = Clasa();//move/copy elision
} 
1

There are 1 best solutions below

0
On BEST ANSWER

In the first case, Clasa c = (Clasa&&)Clasa(); temporary materialization takes place as you're explicitly binding a reference to a prvalue(Class()) and thus no elision here . This can be seen from temporary materialization:

Temporary materialization occurs in the following situations:

  • when binding a reference to a prvalue;

Now coming to the second case of Clasa d = Clasa();.

C++17 & Onwards

Starting from C++17 there is mandatory copy elision. This means that it is mandated by the standard that the object is constructed directly into the storage where it would otherwise be copied/moved to. This essentially means that no copy/move call will be observed here.

Pre-C++17

But prior to C++17, this may result in the creation of a temporary using which d is copy initialized. The same is explained in more detail here.