2016-10-31 1 views
3

J'ai ce C++ extrait de code de test,ne peut pas lier lvalue à la référence rvalue

#include <vector> 

class A { 
     std::vector<int> x; 
public: 
     A(std::vector<int>&& _x) : x(_x) {} 
}; 

class B { 
     A a; 
public: 
     B(std::vector<int>&& _x) : a(/*move(*/_x/*)*/) {} 
}; 

Je passe _x à B comme référence rvalue, mais il devient converti à lValue lorsqu'il est passé dans le constructeur de A et je dois utiliser std::move() pour le faire fonctionner. Ma question est pourquoi _x est lvalue et non une référence de référence dans a()?

+2

Alors que le type de '_x' est une 'référence de valeur r à std :: vector ', il s'agit toujours d'une valeur l car elle a un nom. Vous pourriez vouloir l'utiliser plus d'une fois dans votre constructeur, ainsi il ne devrait pas être déplacé de la première utilisation à moins que vous ne le souhaitiez explicitement. – Corristo

+0

@Corristo pouvez-vous afficher cela comme réponse? – Samik

Répondre

2

Citation de WIKI

Pour des raisons de sécurité, certaines restrictions sont imposées. Une variable nommée ne sera jamais considérée comme une valeur même si elle est déclarée comme telle. Pour obtenir un rvalue, le modèle de fonction std :: move() doit être utilisé. Les références Rvalue peuvent également être modifiées uniquement dans certaines circonstances, étant destinées à être utilisées principalement avec des constructeurs de déplacement.

+0

Wikipedia est imprécis ici. Type et catégorie de valeur sont deux concepts orthogonaux; vous ne pouvez pas * déclarer * la catégorie de valeur. Par exemple. le résultat de l'expression 'dynamic_cast (someObject)' est de type 'lvalue-reference à SomeClass', mais c'est une valeur r. – Corristo

5

Tout ce qui a un nom est une référence lvalue. Vous devez utiliser std :: move sur les paramètres pour les passer en références rvalue.

+5

Ne devrait pas * Tout ce qui a un nom est une référence lvalue * be * Tout ce qui a un nom est un lvalue *? – NathanOliver