Wann wird bei der Rückgabe eines Werts außerhalb einer Funktion "move vs. copy" verwendet?

8

Nach dem Lesen dieser Frage . Ich habe diesen kleinen, kleinen Test erstellt:

%Vor%

Das Ergebnis ist (ohne RVO und NRVO):

  • f verwendet move
  • g verwendet move
  • h verwendet Kopie

Soweit ich weiß, sind die Regeln, die zur Entscheidung über die Verwendung von Kopieren oder Verschieben verwendet werden, in 12.8.32 beschrieben:

  • Wenn die Kriterien für die Eliminierung einer Kopieroperation erfüllt sind oder erfüllt würden, abgesehen von der Tatsache, dass das Quellobjekt ein Funktionsparameter ist und das zu kopierende Objekt durch einen Lvalue gekennzeichnet ist, Die Überladungsauflösung zum Auswählen des Konstruktors für die Kopie wird zuerst so ausgeführt, als ob das Objekt durch einen R-Wert bestimmt würde. ...

Was sich auf die Regeln vom 12.8.31 bezieht: (Ich zeige nur den relevanten Teil)

  • in einer return-Anweisung in einer Funktion mit einem Klassenrückgabetyp, wenn der Ausdruck der Name eines nichtflüchtigen automatischen Objekts (mit Ausnahme eines Parameters function oder catch-clause) ist cvunqualified type als Funktion return type, kann die Operation copy / move weggelassen werden, indem das automatische Objekt direkt in den Rückgabewert der Funktion
  • konstruiert wird
  • wenn ein temporäres Klassenobjekt, das nicht an eine Referenz (12.2) gebunden wurde, kopiert / verschoben wird Bei einem Klassenobjekt mit demselben cv-unqualifizierten Typ kann die Kopier- / Verschiebeoperation weggelassen werden Konstruieren des temporären Objekts direkt in das Ziel der ausgelassenen Kopie / Verschiebung

Nach diesen Regeln verstehe ich, was für f und h passiert:

  • Die Kopie in f kann ausgewählt werden, sodass sie verschoben wird. (Siehe den fett gedruckten Teil)
  • Die Kopie in h ist nicht für Elision geeignet, daher wird sie kopiert.

Was ist mit g?

Für mich sieht es wirklich wie h aus. Ich gebe einen Ausdruck zurück, der nicht der Name eines automatischen Objekts ist, und als solches dachte ich, es würde kopiert werden, aber es wird verschoben. Was geht hier vor sich?

    
Arnaud 28.05.2014, 14:21
quelle

2 Antworten

11

In den meisten Fällen gibt es keinen Unterschied beim Schreiben von a oder (a) . Der relevante Teil der Spezifikation ist §5.1p6 (Hervorhebung von mir):

  

Ein geklammerter Ausdruck ist ein primärer Ausdruck, dessen Typ und Wert mit denen des eingeschlossenen Ausdrucks identisch sind. Das Vorhandensein von Klammern hat keinen Einfluss darauf, ob der Ausdruck ein L-Wert ist. Der in Klammern gesetzte Ausdruck kann in genau denselben Kontexten verwendet werden, in denen der eingeschlossene Ausdruck verwendet werden kann, und mit der gleichen Bedeutung , sofern nicht anders angegeben.

Dasselbe gilt für den Rückgabewert Ihrer Funktion g , wie Sie für f angegeben haben.

In der kommenden Norm C ++ 14 wurde dies verdeutlicht §12.8p32 (Hervorhebung von mir):

  

Wenn die Kriterien für die Eliminierung einer Kopier- / Verschiebungsoperation erfüllt sind, aber nicht für eine Ausnahmedeklaration, und das Objekt, das kopiert werden soll, wird durch einen Lvalue festgelegt, oder wenn der Ausdruck in einer return-Anweisung a ( möglicherweise geklammerter ) ID-Ausdruck, der ein Objekt mit automatischer Speicherdauer im body deklariert oder Parameter-Deklaration-Klausel der innersten umschließenden Funktion oder Lambda-Ausdruck, Überladungsauflösung zuerst den Konstruktor für die Kopie auswählen durchgeführt, als ob das Objekt durch einen rvalue gekennzeichnet wäre.

Für diejenigen, die wissen wollen, wenn die Klammern wichtig sind, hier ein Beispiel:

%Vor%     
MWid 28.05.2014, 15:13
quelle
0

Beachten Sie, dass Sie

deklarieren %Vor%

In Ihren Beispielen werden sie alle kopieren. Abschnitt 12.8 der Norm sagt "Überladungsauflösung Die Auswahl des Konstruktors für die Kopie wird zuerst so durchgeführt, als wäre das Objekt durch einen R-Wert gekennzeichnet, "aber wenn a konstant ist, ist das ein konstanter Wert, der nicht mit dem Move-Konstruktor übereinstimmt.

    
Mark Gilbert 10.11.2015 20:51
quelle

Tags und Links