2016-01-04 25 views
14

Czy w następujących fragmentach jest std::move?Czy konieczne jest tutaj `std :: move`?

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

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

O ile wiem call() przyjmuje odniesienie rvalue .. ale ponieważ odniesienie rvalue jest sama lwartością, w celu wywołania swap(std::function<void(int)>&&) muszę ponownie rzucić to do odniesienia rvalue z std::move

Czy moje rozumowanie jest poprawne lub std::move może zostać pominięte w tym przypadku (a jeśli tak, to dlaczego?)

+1

Wygląda na to, że chcesz wystawić operator = zamiast zamiany tutaj. A potem, tak, użyj ruchu. –

Odpowiedz

18

std::function::swap nie przyjmuje swojego parametru według wartości rwartej. To tylko regular non-const lvalue reference. Tak więc std::move jest niepomocny (i prawdopodobnie nie powinien się kompilować, ponieważ referencje rvalue nie mogą wiązać się z wartościami odniesienia lVN).

other_function również nie musi być referencją rwartości.

11

Podpis jest

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

więc kod nie powinien skompilować z std::move (msvc posiada rozszerzenie, aby umożliwić tę Oprawa: /)

jak wziąć odniesienie wartość R, myślę, że to proste zadanie jest to, co chcesz w przypadku:

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

Brakuje ci punktu fantastycznej magii MSVC2015 – Dean

+2

@ Dean czy ta magia obejmuje zamienić bardzo szybki komputer w gorący blok z plastiku tylko poprzez jego instalację? –

+1

@Dean Er, co? Dlaczego "fantastyczna magia" pozwala, aby rvalue refs wiązało się z nieskończonymi wartościami lvalue? Czy to był sarkazm? –

1

masz rację w pewnym sensie — dostać rvalue ponownie należałoby std::move.

Jednak wywołanie swap nie wymaga wartości r, ani wartości rvalue — tylko zwykłej wartości bezwzględnej.

Więc dobrze jest przejść bez obsady std::move.

Pod względem semantyki ruchu operacja zamiany jest dość niskiego poziomu. Przekonasz się, że najbardziej przydatne ruchy są ostatecznie realizowane przez serię zamian, więc ma sens, że same wymiany nie używają semantyki ruchu. Naprawdę, jak by to zrobili?

3

W tym przypadku nie ma znaczenia, ponieważ std::function::swap przyjmuje wartość stałą o stałej wartości l. Nie powinien nawet kompilować z std::move.

Jeśli użyto funkcji, które zrobił pozwalają rvalues, wtedy byłoby potrzeby zadzwonić std::move jak other_function jest lwartością, choć rodzaj to jest odniesienie RValue. Na przykład:

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

To dodaje cenne informacje, zamiast tylko wspomnieć, że 'swap()' ma odniesienie, co moim zdaniem nie było istotną kwestią. – isanae

Powiązane problemy