2015-09-21 20 views
8

Ho il seguente codice:modo appropriato per trasmettere riferimento rvalue

#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"); 
} 

Nel codice di sopra del void bar(const std::string& str) di sovraccarico viene chiamato. Se desidero chiamare il vuoto bar(std::string&& str), devo scrivere bar(std::move(str)); o bar(std::forward<std::string>(str));

Ovviamente il codice di inoltro è più lungo, ma per me ha più senso. La mia domanda è ciò che è più comunemente usato e preferito. Scrivendo bar(std::forward(str)); sarebbe la soluzione migliore imo, ma che non è un'opzione :)

+3

È possibile spostarlo, in avanti dovrebbe essere utilizzato nel codice di modello quando non si è certi che si tratti di valore o riferimento di lvalue. :) In codice codice && significa riferimento universale, che può essere sia rvalore sia lvalue. – Melkon

+0

@Melko Se si fa il tuo commento una risposta, posso accettarlo :) – rozina

+0

Grazie, lo faccio. :) – Melkon

risposta

6

Citando dal Effective C++ moderno

Dal punto di vista puramente tecnico, la risposta è sì: std :: avanti possibile Fallo tutto. std :: move non è necessario. Certo, nessuna delle due funzioni è davvero necessaria, perché potremmo scrivere cast in tutto il mondo, ma spero che saremo d'accordo sul fatto che sarebbe, beh, schifo. std :: le attrazioni di move sono convenienza, ridotta probabilità di errore e maggiore chiarezza.

Utilizzando std::move qui

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

tornerà str come un riferimento rvalue (che è esattamente quello che stai cercando di raggiungere) durante l'utilizzo std::forward restituirebbe un riferimento di lvalue (che non si è interessato a) o un riferimento di rvalue (quindi equivalente in questo caso a std::move). Ovviamente l'uso di none non farebbe che continuare a chiamare lo const std::string& str poiché str è un lvalue in quella funzione.

Bottom-line: avrebbero fatto la stessa cosa ma con std::move è preferita dal

  • Evita specificare esplicitamente gli argomenti di template
  • E 'più idiomatica
  • va dritto al punto: std::forward non è destinato a essere usato in questo modo (cfr Universal references) o in quel contesto anche se funzionerebbe sicuramente

Potrei essere d'accordo che "sto inoltrando questo riferimento rvalue all'altra funzione" potrebbe avere senso come una frase autonoma, ma in qualche modo manca il punto della questione. Si potrebbe ri-wire il cervello a pensare che come "mantenere 'in movimento' questo riferimento rvalue all'altra funzione di"

anche possibilmente correlati: https://stackoverflow.com/a/18214825/1938163

3

È possibile spostare ogni volta che si è sicuri che sia un rvalue riferimento.

Inoltra deve essere utilizzato nel codice di modello quando non si può essere certi se si tratta di un valore o un riferimento di lvalue. :)

Nel codice & & significa riferimento universale, che può essere sia rvalore sia lvalue.

Inoltre, nota che std :: move lo sta rilasciando senza alcun controllo, diversamente da avanti, quindi mentre in avanti è più sicuro se non sei sicuro di cosa dovresti fare, lo spostamento è più veloce.

Problemi correlati