2013-06-27 7 views
10

Für bewegungsaktivierte Klassen gibt es einen Unterschied zwischen diesen beiden?Überschreiten Sie durch Wert oder rvalue-ref

struct Foo { 
typedef std::vector<std::string> Vectype; 
Vectype m_vec; 
//this or 
void bar(Vectype&& vec) 
{ 
    m_vec = std::move(vec); 
} 
//that 
void bar(Vectype vec) 
{ 
    m_vec = std::move(vec); 
} 
}; 
int main() 
{ 
    Vectype myvec{"alpha","beta","gamma"}; 
    Foo fool; 
    fool.bar(std::move(myvec)); 
} 

Mein Verständnis ist, dass wenn Sie ein L-Wert verwenden myvec Sie auch const Vectype& Version von Foo::bar() seit Vectype&& einzuführen erforderlich wird nicht binden. Abgesehen davon wird Foo::bar(Vectype) im Rvalue-Fall den Vektor mit dem Move-Konstruktor konstruieren oder besser noch mit der Kopie, die alle zusammen vec ist ein Rvalue (oder?). Gibt es also einen zwingenden Grund, die Deklaration nach Wert anstelle von lvalue und rvalue overloads zu bevorzugen? (Überlege, dass ich den Vektor auf jeden Fall in die Elementvariable kopieren muss.)

+0

vor jeder Pedanterie Ich weiß, dass die Überlastungen zweideutig sind. –

Antwort

3

Die Funktion "Pass-by-Value" ist ausreichend (und äquivalent), solange der Argumenttyp über einen effizienten Bewegungskonstruktor verfügt, der in diesem Fall für std::vector gilt.

Andernfalls kann die Verwendung der Funktion "Pass-By-Value" eine zusätzliche Kopiekonstruktion im Vergleich zur Verwendung der Funktion "Pass-by-Rvalue-Ref" einführen.

Siehe die Antwort https://stackoverflow.com/a/7587151/1190077 auf die verwandte Frage Do I need to overload methods accepting const lvalue reference for rvalue references explicitly?.

2

Ja, die erste (Vectype&& vec) akzeptiert kein konstantes Objekt oder nur lvalue.

Wenn Sie das Objekt wie gewünscht speichern möchten, kopieren Sie es am besten (oder verschieben es, wenn Sie einen rvalue übergeben) und bewegen Sie es dann wie im zweiten Beispiel.

5

Die Pass-by-Value-Version ermöglicht ein Lvalue-Argument und erstellt eine Kopie davon. Die Rvalue-Referenzversion kann nicht mit einem Lvalue-Argument aufgerufen werden.

Verwenden const Type& wenn Sie brauchen, um überhaupt nicht oder kopieren Sie ändern das Argument, verwenden Pass-by-Wert, wenn Sie einen änderbaren Wert wollen, aber egal, wie Sie es erhalten, und Type& und Type&& Überlastungen verwenden, wenn Sie möchten, dass je nach Kontext etwas anderes passiert.

Verwandte Themen