0

Could you explain me why, in the following, code,

#include <iostream>
#include <variant>
#include <string>



class MySecondType {
public:
    MySecondType() { std::cout << "Constructeur par défaut de MySecondType\n"; }
    MySecondType(const MySecondType&) // Constructeur par copie
    {std::cout<< "Constructeur par copie de MySecondType\n";}
    MySecondType(MySecondType&&) noexcept//Constructeur par déplacement 
    {
        std::cout << "COnstructeur par déplacement de MySecondType\n";
    }


    MySecondType& operator=(MySecondType&&) noexcept
    {
        std::cout << "Opérateur d'affection par déplacement\n";
        return *this;
    }

    MySecondType& operator=(MySecondType&) 
    {
        std::cout << "Opérateur d'affection par copie\n";
        return *this;
    }



    ~MySecondType() {
        std::cout << "Destructeur de MySecondType\n";
    }

};


int main() {

    MySecondType e;
    e= MySecondType() ;
return 0;
}

I have the result I wait, with :

MySecondType e;
e= MySecondType() ;

BUT I don't have it , if I do :

MySecondType e = MySecondType() ;

I expected that the line :

MySecondType e = MySecondType() ;

would call the move constructor(after the default constructor), but it does not call it. It only creates an object with the default constructor , and that's nothing else.

Can you explain me why ?

Thank you

Dev
  • 463
  • 3
  • 12
  • 2
    You need to assign to a variable. try `MySecondType e = MySecondType()` – Jacob Feb 16 '20 at 09:41
  • 1
    Does this answer your question? [What are copy elision and return value optimization?](https://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization) – L. F. Feb 16 '20 at 09:53
  • 1
    FYI: [SO: What are copy elision and return value optimization?](https://stackoverflow.com/a/12953129/7478597). For the record: `MySecondType e; e= MySecondType();` is assignment but `MySecondType e = MySecondType() ;` is initialization. About, `MySecondType = MySecondType();` (with missing variable name) I'm not 100 % sure but I strongly guess it's the same. – Scheff's Cat Feb 16 '20 at 09:54
  • I have edited the message and added the missing e when it was missing – Dev Feb 16 '20 at 10:18
  • Note that your copy construcor is incorrect, it takes its argument by non-const lvalue-reference, while it should be taking it by const lvalue-reference. – AVH Feb 16 '20 at 10:30
  • I think you better mean my copy assignment operator, not my copy constructor , which is correct. – Dev Feb 16 '20 at 10:34
  • @Darhuuk the non-const version is legal, but it's considered bad style – M.M Feb 16 '20 at 11:03
  • @Dev Indeed, I meant the copy assignment operator. – AVH Feb 16 '20 at 13:18

1 Answers1

2

I'm asuming you actually do what @Jacob hinted at, i.e. MySecondType e = MySecondType();.

If so, then the compiler is eliding the copy/move constructor. It sees that you are creating a temporary object and right after assigning it to a variable. So instead of doing that, which would be inefficient, it skips the copy/move step and directly constructs the object at its final destination.

AFAIK, this is an optional optimization pre-C++17. Starting in C++17 it's mandatory.

AVH
  • 11,349
  • 4
  • 34
  • 43