2015-10-05 1 views
0

J'essayais un programme sur les références universelles en appliquant std::move et std::forward sur eux. Jusqu'à aujourd'hui j'ai supposé que les deux étaient les mêmes mais dans ce programme même (donné ci-dessous) la sortie m'a étonné.déplacer vs transmettre sur les références universelles

#include <iostream> 
#include <string> 
#include <utility> 
using namespace std; 

class X 
{ 
    string take=""; 
    public: 
    template<class T> 
    void pass1 (T &&str) // str is a universal reference as it can bind to anything, both rvalue and lvalue references 
    { 
     take=move(str); 
    } 
    template<class T> 
    void pass2 (T &&str) 
    { 
     take=forward<T>(str); 
    } 
    void show() 
    { 
     cout<<"take = "<<take<<"\n"; 
    } 
}obj; 

int main() 
{ 
    cout<<"using move on universal reference:-\n"; 
    string str="he is there"; 
    cout<<"str = "<<str<<'\n'; 
    obj.pass1(str); 
    obj.show(); 
    if (str.empty()) 
    cout<<"str is empty\n\n"; 
    else 
    cout<<"str isnt empty\n\n"; 
    cout<<"using forward on universal reference:-\n"; 
    str="he was there"; 
    cout<<"str = "<<str<<'\n'; 
    obj.pass2(str); 
    obj.show(); 
    if (str.empty()) 
    cout<<"str is empty\n\n"; 
    else 
    cout<<"str isnt empty\n\n"; 
    return 0; 
} 

Sortie:

using move on universal reference:- 
str = he is there 
take = he is there 
str is empty 

using forward on universal reference:- 
str = he was there 
take = he was there 
str isnt empty 
*/ 

Mes questions sont les suivantes:

  1. Pourquoi les sorties différentes?
  2. Ne pas move et forward fonctionnent de manière similaire? Comment fonctionnent-ils différemment (dans le contexte du code ci-dessus)?
+0

Utilisez 'move' avec des références rvalue et' forward 'avec des références de transfert (" universal "). –

+2

Et quelle est la question? – Jarod42

+1

Duplicates: http://stackoverflow.com/q/9671749, http://stackoverflow.com/q/13219484 –

Répondre

0

références universelles signifient qu'ils peuvent se lier avec apparemment quoi que ce soit, les deux rvalues ​​et lvalues. DONNEZ TOUT ce qui est LITTERALEMENT et effectuez plutôt des lancements, c'est-à-dire qu'ils jettent l'argument à rvalue. La différence est que move émet inconditionnellement tandis que forward va lancer conditionnellement: il ne jette à une valeur que si son argument a été initialisé avec une valeur. Donc, move jette toujours tandis que forward jette parfois. Par conséquent, le forward dans le cas ci-dessus ne vide pas la chaîne car un lvalue (ie str) a été passé, donc il a été envoyé str en tant que lvalue.

+0

Merci pour une réponse plus simple! – Anwesha

+1

Vérifiez les «moyens spécifiques efficaces de C++: 42 de Scott Meyer pour améliorer votre utilisation de C++ 11 et C++ 14» pour de meilleures explications. Bonne chance ! –

2

Ils sont différents, bien sûr. Si elles étaient identiques, vous n'en auriez besoin que d'une.

move construit rvalue à partir de rvalue fourni ou lvalue. forward déchiffre le type réel de l'argument fourni.

2

T && a été renommé en référence de renvoi.

Dans votre premier exemple, vous appelez explicitement std::move alors str devient une référence de valeur r et son contenu est déplacé de principal vers le membre dans X.

Dans le deuxième exemple, vous utilisez std::forward. appeler std::forward sur T lorsque T est une référence de valeur r transmettra la référence de valeur r à operator= et operator=(std::String&&) sera appelée. Si T est une valeur l alors une référence de valeur l est passée. Puisque nous avons une valeur l, le operator=(const std::string&) sera appelé et nous copierons str au lieu de le déplacer.

1

deux Understand chose:

1) 'déplacer' ne garantit pas se déplacer

2) 'avant' ne transférera pas de code.

déménagement est un opérateur inconditionnel

avant est un opérateur conditionnel.

Confus ??

s'il vous plaît regarder cette vidéo: https://www.youtube.com/watch?v=BezbcQIuCsY