2016-01-04 17 views
14

Ist std::move im folgenden Code-Schnipsel erforderlich?Ist `std :: move 'hier notwendig?

std::function<void(int)> my_std_function; 

void call(std::function<void(int)>&& other_function) 
{ 
    my_std_function.swap(std::move(other_function)); 
} 

Soweit ich call() akzeptiert eine rvalue Referenz wissen .. aber da die rvalue Referenz selbst einen L-Wert, um swap(std::function<void(int)>&&) zu nennen ich dies mit std::move

zu rvalue Referenz erneut gegossen habe

Ist meine Argumentation korrekt oder std::move kann in diesem Fall weggelassen werden (und wenn es kann, warum?)

+1

Scheint, Sie möchten Operator = anstelle von hier tauschen. Und dann, ja, benutze move. –

Antwort

18

std::function::swap nimmt seinen Parameter nicht durch Rvalue-Referenz. Es ist nur ein regular non-const lvalue reference. Daher ist std::move nicht hilfreich (und sollte wahrscheinlich nicht kompiliert werden, da rvalue-Referenzen nicht an l0val-Referenzen binden dürfen).

other_function muss auch keine rvalue-Referenz sein.

11

Die Signatur ist

void std::function<Sig>::swap(function& other) 

so Code sollte nicht mit std::move kompilieren (msvc Erweiterung hat diese Bindung zu ermöglichen: /)

Wie Sie r-Wert Bezug nehmen, denke ich, dass eine einfache Zuordnung in Ihrem Fall ist das, was Sie wollen:

std::function<void(int)> my_std_function; 

void call(std::function<void(int)>&& other_function) 
{ 
    my_std_function = std::move(other_function); // Move here to avoid copy 
} 
+1

Sie vermissen den Punkt der fantastischen Magie von MSVC2015 – Dean

+2

@De würde diese Magie umfassen, einen sehr schnellen Computer in einen heißen Block des Plastiks nur durch das Installieren zu verwandeln? –

+1

@Dean Er, was? Warum ist es "fantastische Magie", rValue-Referenzen an nicht-konstante Lvalue-Refs binden zu können? War das Sarkasmus? –

1

Sie haben Recht, in einem gewissen Sinne — rvalue zu bekommen wieder würden Sie std::move benötigen.

Der Aufruf swap erfordert jedoch keinen R-Wert oder eine R-Wert-Referenz — nur eine einfache ol 'lval ref.

Sie sind also gut ohne die std::move Besetzung zu gehen.

In Bezug auf Verschieben Semantik ist eine Swap-Operation ziemlich Low-Level. Sie werden feststellen, dass die meisten nützlichen Moves letztlich durch eine Reihe von Swaps implementiert werden. Daher ist es sinnvoll, dass die Swaps selbst keine move-Semantik verwenden. Wirklich, wie würden sie?

3

In diesem Fall macht das keinen Unterschied, da std::function::swap eine nicht konstante Lvalue-Referenz verwendet. Es sollte nicht einmal mit std::move kompilieren.

Wenn Sie eine Funktion verwendet, die tat rvalues ​​erlauben, dann sind Sie würde Notwendigkeit std::move als other_function zu nennen ein L-Wert ist, auch wenn die Art der es sich um eine rvalue Referenz. Zum Beispiel:

struct Foo { 
    Foo()=default; 
    Foo(const Foo&) { std::cout << "copy" << std::endl; } 
    Foo(Foo&&) { std::cout << "move" << std::endl; } 
}; 

void bar (Foo&& a) { 
    Foo b {a};   //copy 
    Foo c {std::move(a)}; //move 
} 
+0

Dies fügt wertvolle Informationen hinzu, anstatt nur zu erwähnen, dass 'swap()' einen Verweis enthält, was meiner Meinung nach nicht wirklich der Punkt der Frage war. – isanae