Nach dem Lesen dieser Frage . Ich habe diesen kleinen, kleinen Test erstellt:
%Vor%Das Ergebnis ist (ohne RVO und NRVO):
Soweit ich weiß, sind die Regeln, die zur Entscheidung über die Verwendung von Kopieren oder Verschieben verwendet werden, in 12.8.32 beschrieben:
Was sich auf die Regeln vom 12.8.31 bezieht: (Ich zeige nur den relevanten Teil)
Nach diesen Regeln verstehe ich, was für f und h passiert:
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?
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%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.