Pourquoi ne puis-je pas faire un vecteur de références?
Quand je fais ceci:
std::vector<int> hello;
Tout fonctionne très bien. Cependant, lorsque je fais un vecteur de références à la place:
std::vector<int &> hello;
- Je obtenir horribles erreurs comme
erreur C2528: 'pointeur' : pointeur de référence est illégal
Je veux mettre un tas de références à des structures dans un vecteur, de sorte que je n'ai pas à interférer avec les pointeurs. Pourquoi est vecteur de jeter une crise de colère à ce sujet? Est ma seule option pour utiliser un vecteur de pointeurs au lieu de cela?
- vous pouvez utiliser std::vector<reference_wrapper<int> > bonjour; Voir informit.com/guides/content.aspx?g=cplusplus&seqNum=217
- le lien est valide n'est plus, la documentation officielle ici
Vous devez vous connecter pour publier un commentaire.
Le type de composant de conteneurs tels que les vecteurs doivent être assignables. Les références ne sont pas cessibles (vous ne pouvez initialiser une fois lorsqu'ils sont déclarés, et vous ne pouvez pas faire référence à quelque chose d'autre plus tard). D'autres non-cessible types ne sont pas autorisés en tant que composants de conteneurs, par exemple
vector<const int>
n'est pas autorisé.vector<vector <int>&>
La solution a été de travailler avec:vector<vector<int>*>
static_assert<std::is_same_v<T, std::remove_reference<T>>>
ou quelque chose le long de ces lignesoui, vous pouvez regarder pour
std::reference_wrapper
, qui imite une référence mais est cessible et peut également être "réinstaller"get()
premier lorsque vous tentez d'accéder à une méthode d'une instance d'une classe dans le conteneur? E. g.reference_wrapper<MyClass> my_ref(...); my_ref.get().doStuff();
n'est pas très référence..get()
. Ce timdiels veut, c'estoperator.
; avoir un regard sur les dernières propositions de discussions à ce sujet.De par leur nature même, les références ne peuvent être définies à la fois qu'ils sont créés; c'est à dire, les deux lignes suivantes ont des effets très différents:
Plus loin, ce qui est illégal:
Toutefois, lorsque vous créez un vecteur, il n'existe aucun moyen pour affecter des valeurs à des éléments lors de la création. Vous êtes essentiellement faire tout un tas de de la dernier exemple.
Ion Todirel déjà mentionné une réponse OUI à l'aide de
std::reference_wrapper
. Depuis C++11 nous avons un mécanisme permettant de récupérer l'objet à partirstd::vector
et de supprimer la référence à l'aide destd::remove_reference
. Ci-dessous est donné un exemple compilé à l'aide deg++
etclang
avec l'option-std=c++11
et exécutée avec succès.std::remove_reference<>
ici. Le point destd::remove_reference<>
est de vous permettre d'écrire "le type T, mais sans être une référence, si c'en est un". Doncstd::remove_reference<MyClass&>::type
est juste le même que l'écriture deMyClass
.for (MyClass obj3 : vec) std::cout << obj3.getval() << "\n";
(oufor (const MyClass& obj3: vec)
si vous déclarezgetval()
const, comme vous devriez le savoir).boost::ptr_vector<int>
fonctionne.Edit: était une suggestion pour l'utilisation
std::vector< boost::ref<int> >
, qui ne fonctionnera pas parce que vous ne pouvez pas par défaut-la construction d'unboost::ref
.resize
.C'est une faille dans le langage C++. Vous ne pouvez pas prendre l'adresse d'une référence, depuis la tentative de le faire entraînerait l'adresse de l'objet visé, et donc vous pouvez ne jamais obtenir un pointeur vers une référence.
std::vector
travaille avec des pointeurs de ses éléments, de sorte que les valeurs stockées doivent être en mesure d'être souligné. Vous aurez à utiliser des pointeurs au lieu.sizeof
une référence.Comme d'autres l'ont mentionné, vous aurez probablement jusqu'à la fin à l'aide d'un vecteur de pointeurs au lieu.
Cependant, vous pouvez envisager d'utiliser un ptr_vector la place!
TL; DR
Utilisation
std::reference_wrapper
comme ceci:Démo
Réponse longue
Comme norme suggère, pour un conteneur standard
X
contenant des objets de typeT
,T
doit êtreErasable
deX
.Erasable
signifie que l'expression suivante est bien formé:A
est du conteneur de l'allocateur de type,m
est allocateur de l'instance etp
est un pointeur de type*T
. Voir ici pourErasable
définition.Par défaut,
std::allocator<T>
est utilisé comme vecteur de l'allocateur. Avec la valeur par défaut de l'allocateur, l'exigence est équivalent à la durée de validité dep->~T()
(Note de l'T
est un type de référence etp
est pointeur vers une référence). Cependant, pointeur vers une référence est illégal, d'où l'expression n'est pas bien formé.Comme les autres commentaires le suggèrent, vous êtes confiné à l'aide de pointeurs.
Mais si cela peut aider, voici une technique pour éviter de faire face directement avec les pointeurs.
Vous pouvez faire quelque chose comme ce qui suit:
reinterpret_cast
n'est pas nécessaire