2015-09-21 1 views
8

Je le code suivant:manière appropriée de transmettre la référence 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"); 
} 

Dans le code ci-dessus la void bar(const std::string& str) surcharge est appelée. Si je veux le vide bar(std::string&& str) surcharge à appeler soit je dois écrire bar(std::move(str)); ou bar(std::forward<std::string>(str));

Il est évident que le code est plus en avant, mais il est plus logique pour moi. Ma question est ce qui est le plus couramment utilisé et préféré. L'écriture bar(std::forward(str)); serait la meilleure solution imo, mais ce n'est pas une option :)

+3

Vous pouvez le déplacer, l'avant devrait être utilisé dans le code de modèle si vous ne pouvez pas être sûr si c'est la référence de rvalue ou de lvalue. :) Dans le code modélisé && signifie référence universelle, qui peut être soit rvalue ou lvalue. – Melkon

+0

@Melko Si vous faites votre commentaire une réponse, je peux l'accepter :) – rozina

+0

Merci, je le fais. :) – Melkon

Répondre

6

Citant de moderne et efficace C++

Du point de vue purement technique, la réponse est oui: std :: avant peut fait tout. std :: move n'est pas nécessaire. Bien sûr, aucune des deux fonctions n'est vraiment nécessaire, car nous pourrions écrire des moulages partout, mais j'espère que nous sommes d'accord que ce serait, eh bien, dégueulasse. Les attractions de std :: move sont la commodité, la probabilité réduite d'erreur et une plus grande clarté.

En utilisant std::move ici

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

retournera str comme référence rvalue (ce qui est exactement ce que vous essayez d'atteindre) tout en utilisant std::forward renverrait soit une référence lvalue (que vous n'êtes pas intéressé par) ou une référence rvalue (donc équivalente dans ce cas à std::move). Évidemment, en utilisant aucun ne continuerait à appeler le const std::string& str puisque str est un lvalue dans cette fonction.

Bottom line: ils feraient la même chose mais en utilisant std::move est préféré depuis

  • Il évite de préciser explicitement les arguments de modèle
  • Il est plus idiomatiques
  • Il va droit au but: std::forward n'est pas destiné à être utilisé de cette façon (cfr Universal references) ou dans ce contexte bien que cela fonctionnerait sûrement

Je pourrais convenir que "Je transmets cette référence rvalue à l'autre fonction" pourrait avoir un sens comme une phrase autonome, mais il manque en quelque sorte le point de la question. Vous pouvez recâbler votre cerveau à penser comme « keep « mouvement » cette référence rvalue à l'autre fonction »

Aussi peut-être liée: https://stackoverflow.com/a/18214825/1938163

3

Vous pouvez déplacer chaque fois que vous êtes sûr qu'il est un rvalue référence.

Le code vers l'avant doit être utilisé dans le code basé sur un modèle lorsque vous ne pouvez pas être sûr s'il s'agit d'une référence rvalue ou lvalue. :)

Code basé sur le modèle & & référence universelle, qui peut être soit rvalue soit lvalue.Notez également que std :: move le lance sans aucune vérification, contrairement à l'avance, donc si l'avance est plus sûre si vous n'êtes pas sûr de ce que vous devez faire, le déplacement est plus rapide.