Move Constructor vs Copy Elision. Welches wird angerufen?

Ich habe hier zwei Code-Teile, die ich Ihnen zeigen möchte. Es handelt sich um zwei Klassen, von denen jede einen Verschiebungskonstruktor und eine Funktion enthält, die ein temporäres Ergebnis liefert.

Im ersten Fall ruft die Funktion, die ein temporäres @ zurückgibt, das @ auMove Constructor Im zweiten Fall weist die Funktion, die ein temporäres Objekt zurückgibt, den Compiler an, ein @ auszuführecopy elision

Ich bin verwirrt: In beiden Fällen definiere ich einen Move-Konstruktor und eine zufällige Member-Funktion, die eine temporäre zurückgibt. Aber das Verhalten ändert sich und meine Frage istWaru.

Beachten Sie, dass in den folgenden Beispielen der Operator << überladen wurde, um eine Liste (im ersten Fall) und das doppelte Datenelement (im zweiten Fall) zu drucken.

MOVE CONSTRUCTOR wird aufgerufen

template<typename T>
class GList
{
public:
    GList() : il{ nullptr } {}

    GList(const T& val) : il{ new Link<T>{ val,nullptr } }  {}

    GList(const GList<T>& copy) {}

    GList(GList<T>&& move)
    {
        std::cout << "[List] Move constructor called" << std::endl;

        // ... code ...
    }

    // HERE IS THE FUNCTION WHICH RETURNS A TEMPORARY!
    GList<T> Reverse()
    {
        GList<T> result;

        if (result.il == nullptr)
            return *this;

        ...
        ...
        ...

        return result;
    }
};

int main()
{

   GList<int> mylist(1);

   mylist.push_head(0);

   cout << mylist.Reverse();

   return 0;
}

Die Ausgabe ist:

[Liste] Konstruktor mit dem Namen @ verschieb

0

1

COPY ELISION PERFORMED

class Notemplate
{
   double d;
public:
   Notemplate(double val)
   {
      d = val;
   }

   Notemplate(Notemplate&& move)
   {
       cout << "Move Constructor" << endl;
   }

   Notemplate(const Notemplate& copy)
   {
       cout << "Copy" << endl;
   }

   Notemplate Redouble()
   {
       Notemplate example{ d*2 };
       return example;
   }
};

int main()
{
   Notemplate my{3.14};

   cout << my.Redouble();

   return 0;
}

Die Ausgabe ist:

6.28

Ich habe im zweiten Beispiel einen Aufruf des Move-Konstruktors erwartet. Immerhin ist die Logik für die Funktion dieselbe: gib eine temporäre zurück.

Wird mir jemand erklären, warum das nicht passiert?

Wie gehe ich mit Kopierentscheidungen um?

Ich möchte, dass mein Code so portabel wie möglich ist. Wie kann ich sicher sein, dass der Compiler solche Optimierungen vornimmt?

Antworten auf die Frage(4)

Ihre Antwort auf die Frage