2013-08-24 4 views
6

Ich schreibe eine Implementierung von Standard-C++ - Bibliothek für die Studie.Returning std :: move (f) in std :: for_each

Der C++ 11-Standard besagt, dass for_eachstd::move(f) zurückgibt.

Ich dachte, dass Funktion Bereich lokale Variable ist Move-konstruiert, wenn es zurückgegeben wird. Soll ich explizit move(f) zurückgeben?

+3

In diesem Fall entspricht die Rückgabe von 'std :: move (f)' * fast * der Rückgabe von 'f'. C++ 11 verbietet die Rückgabewertoptimierung für Funktionsparameter (erlaubt aber trotzdem implizite Verschiebung für sie). Der einzige Unterschied, so scheint es mir, ist, dass 'return f;' auf a zurückfällt und es als lvalue betrachtet, wenn der rvalue eine Überlastungsambiguität verursachen würde oder keinen Konstruktor finden würde. Aber 'Rückkehrbewegung (f)' würde in einem solchen Fall mit Ungereimtheit versagen. –

+1

Zum Beispiel wäre das Verhalten für eine 'Funktion' unterschiedlich, die wie folgt definiert ist: struct Funktion {Function (Function &); }; '. Diese Klasse hat keinen Verschiebungskonstruktor und einen Kopierkonstruktor, der rvalues ​​nicht akzeptiert. Die 'move (f)' return wäre daher schlecht geformt, während die 'return f;' wohlgeformt wäre. –

+1

Aber ich bin mir nicht sicher, was die Bibliothekseinschränkungen für Funktionsobjekte sind. Vielleicht benötigen sie 'Function', um eine Kopie von rvalues ​​zu initialisieren. In diesem Fall gäbe es tatsächlich keine Unterschiede, soweit ich das beurteilen kann. –

Antwort

2

Von Josuttis ‚s Die C++ Standard Library

Sie müssen nicht und sollte nicht() Rückgabewerte bewegen. Nach den Sprachregeln gibt die Norm, dass für den folgenden Code

X foo() 
{ 
X x; 
... 

return x; 
} 

das folgende Verhalten garantiert:

• Wenn X eine leicht zugängliche Kopie oder verschieben Konstruktor hat, kann der Compiler wählen die elide Kopieren. Dies ist der so genannte (named) Rückgabewert Optimierung ((N) RVO), die bereits vor C++ 11 angegeben wurde und von den meisten Compilern unterstützt wird.

• Andernfalls, wenn X einen Move-Konstruktor hat, wird x verschoben.

• Andernfalls, wenn X einen Kopierkonstruktor hat, wird x kopiert.

• Andernfalls wird ein Fehler bei der Kompilierung ausgegeben.

Von §25.2.4 (for_each)

Benötigt: Funktion muss die Anforderungen der MoveConstructible (Tabelle 20) erfüllen. [Hinweis: Funktion nicht die Anforderungen des CopyConstructible (Tabelle 21) .- Endnote erfüllen muß]

Mit std::move(f) Sie in der Lage, gewährleistet werden können, die den mutierte Zustand von außen zu lesen.

+0

Ich habe die Anforderung von 'Funktion' verpasst. Danke. – kukyakya

+1

Allerdings fragt die Frage nach einem Funktionsparameter "f", während der Standard stattdessen ein Beispiel mit einer lokalen Variablen angibt. Gilt RVO für Funktionsparameter? – Hugues