2015-09-21 11 views
8

Mam następujący kod:odpowiedni sposób do przekazania rvalue Reference

#include <iostream> 
#include <string> 

using std::cout; 
using std::endl; 

void bar(const std::string& str) 
{ 
    cout << "const str - " << str << endl; 
} 

void bar(std::string&& str) 
{ 
    cout << "str - " << str << endl; 
} 

void foo(std::string&& str) 
{ 
    bar(str); 
} 


int main() 
{ 
    foo("Hello World"); 
} 

w powyższym kodzie przeciążenie void bar(const std::string& str) jest wywoływana. Jeśli chcę przeciążenie void bar(std::string&& str) nazywać I albo trzeba napisać bar(std::move(str)); lub bar(std::forward<std::string>(str));

Oczywiście kod przodu jest dłuższy, ale to sprawia, że ​​więcej sensu dla mnie. Moje pytanie dotyczy tego, co jest częściej używane i preferowane. Pisanie bar(std::forward(str)); byłoby najlepszym rozwiązaniem imo, ale to nie jest opcja :)

+3

Możesz go przenieść, do przodu należy użyć w szablonie kodu, gdy nie możesz być pewien, czy jest to wartość r lub wartość l. :) W templated code && oznacza odniesienie uniwersalne, które może być albo wartością r, albo lwartością. – Melkon

+0

@Melko Jeśli skomentujesz odpowiedź, mogę ją zaakceptować :) – rozina

+0

Dzięki, robię to. :) – Melkon

Odpowiedz

6

Powołując z skutecznych, nowoczesnych C++

Z punktu widzenia czysto technicznego, odpowiedź brzmi tak: std :: naprzód może Zrób to wszystko. std :: move nie jest konieczne. Oczywiście żadna funkcja nie jest naprawdę potrzebna, ponieważ wszędzie można pisać odlewy, ale mam nadzieję, że się zgodzimy, że to będzie, no cóż, obrzydliwe. atrakcje std :: move to wygoda, mniejsze prawdopodobieństwo błędu i większa przejrzystość.

Korzystanie std::move tutaj

void foo(std::string&& str) 
{ 
    bar(str); 
} 

powróci str jako odniesienie rvalue (co jest dokładnie to, co starasz się osiągnąć) podczas korzystania std::forward wróci albo odwołanie lwartości (co nie jesteś zainteresowany) lub wartości odniesienia rwartości (w związku z tym równoważne z std::move). Oczywiście użycie tego nie będzie po prostu wywoływać const std::string& str od str jest lwartością w tej funkcji.

dolna linia: zrobiliby to samo, ale używając std::move jest korzystna, ponieważ

  • unika jawnie określając argumenty szablonu
  • Jest bardziej idiomatyczne
  • To idzie prosto do punktu: std::forward nie jest przeznaczony do użycia w ten sposób (patrz: Universal references) lub w tym kontekście, chociaż z pewnością zadziałałby on:

Mogę zgodzić się, że "Przekazuję tę referencję rvalue do innej funkcji" może mieć sens jako samodzielne zdanie, ale to nie trafia w sedno sprawy. Można ponownie drut twój mózg do myślenia to jak „Twierdzy«ruchomym»to odniesienie rvalue do innej funkcji

także ewentualnie powiązanych: https://stackoverflow.com/a/18214825/1938163

3

Można przenieść go, gdy jesteś pewien, że to rvalue odniesienie.

Przekaż dalej należy używać w kodzie szablonowym, gdy nie można mieć pewności, czy jest to wartość r lub wartość lwartości. :)

Kod na szablonie & & średnia wartość odniesienia, która może być wartością r lub l.

Należy również zauważyć, że std :: move przesyła ją bez żadnego czeku, w przeciwieństwie do naprzód, więc podczas gdy naprzód jest bezpieczniejszy, jeśli nie jesteś pewien, co powinieneś zrobić, ruch jest szybszy.

Powiązane problemy