Quand je fais ça:
std::vector<int> hello;
Tout fonctionne très bien. Cependant, lorsque j'en fais plutôt un vecteur de références:
std::vector<int &> hello;
J'ai des erreurs horribles comme
erreur C2528: 'pointeur': le pointeur vers la référence est illégal
Je veux mettre un tas de références à des structures dans un vecteur, afin de ne pas avoir à me mêler de pointeurs. Pourquoi le vecteur fait-il une crise de colère à ce sujet? Est-ce ma seule option pour utiliser un vecteur de pointeurs à la place?
Réponses:
Le type de composant des conteneurs comme les vecteurs doit être assignable . Les références ne sont pas assignables (vous ne pouvez les initialiser qu'une seule fois lorsqu'elles sont déclarées et vous ne pouvez pas les faire référencer autre chose plus tard). D'autres types non attribuables ne sont pas non plus autorisés en tant que composants de conteneurs, par exemple
vector<const int>
n'est pas autorisé.la source
oui vous pouvez, chercher
std::reference_wrapper
, qui imite une référence mais est assignable et peut également être "réinstallé"la source
get()
premier lorsque vous essayez d'accéder à une méthode d'une instance d'une classe dans ce wrapper? Par exemple, cereference_wrapper<MyClass> my_ref(...); my_ref.get().doStuff();
n'est pas une référence très semblable..get()
. Ce que veut timdiels, c'estoperator.
; jetez un œil aux dernières propositions / discussions à ce sujet.De par leur nature même, les références ne peuvent être établies qu'au moment de leur création; c'est-à-dire que les deux lignes suivantes ont des effets très différents:
En plus, c'est illégal:
Cependant, lorsque vous créez un vecteur, il n'y a aucun moyen d'attribuer des valeurs à ses éléments lors de la création. Vous faites essentiellement tout un tas du dernier exemple.
la source
Ion Todirel a déjà mentionné une réponse OUI en utilisant
std::reference_wrapper
. Depuis C ++ 11, nous avons un mécanisme pour récupérer l'objetstd::vector
et supprimer la référence en utilisantstd::remove_reference
. Ci-dessous est donné un exemple compilé en utilisantg++
etclang
avec option-std=c++11
et exécuté avec succès.la source
std::remove_reference<>
ici. Le butstd::remove_reference<>
est de vous permettre d'écrire "le type T, mais sans être une référence s'il en est un". Il enstd::remove_reference<MyClass&>::type
va de même pour l'écritureMyClass
.for (MyClass obj3 : vec) std::cout << obj3.getval() << "\n";
(oufor (const MyClass& obj3: vec)
si vous déclarezgetval()
const, comme vous le devriez).boost::ptr_vector<int>
marchera.Edit: était une suggestion à utiliser
std::vector< boost::ref<int> >
, qui ne fonctionnera pas car vous ne pouvez pas construire par défaut unboost::ref
.la source
resize
.C'est une faille dans le langage C ++. Vous ne pouvez pas prendre l'adresse d'une référence, car tenter de le faire entraînerait l'adresse de l'objet auquel il est fait référence, et vous ne pouvez donc jamais obtenir un pointeur vers une référence.
std::vector
fonctionne avec des pointeurs vers ses éléments, de sorte que les valeurs stockées doivent pouvoir être pointées. Vous devrez utiliser des pointeurs à la place.la source
sizeof
référence a.TL; DR
Utilisez
std::reference_wrapper
comme ceci:Demo
Longue réponse
Comme le suggère la norme , pour un conteneur standard
X
contenant des objets de typeT
,T
doit êtreErasable
deX
.Erasable
signifie que l'expression suivante est bien formée:A
est le type d'allocateur du conteneur,m
est une instance d'allocateur etp
est un pointeur de type*T
. Voir ici pour laErasable
définition.Par défaut,
std::allocator<T>
est utilisé comme allocateur de vecteur. Avec l'allocateur par défaut, l'exigence est équivalente à la validité dep->~T()
(Notez qu'ilT
s'agit d'un type de référence etp
d'un pointeur sur une référence). Cependant, le pointeur vers une référence est illégal , d'où l'expression n'est pas bien formée.la source
Comme d'autres l'ont mentionné, vous finirez probablement par utiliser un vecteur de pointeurs à la place.
Cependant, vous voudrez peut-être envisager d'utiliser un ptr_vector à la place!
la source
Comme les autres commentaires le suggèrent, vous êtes limité à utiliser des pointeurs. Mais si cela peut aider, voici une technique pour éviter de faire face directement aux pointeurs.
Vous pouvez faire quelque chose comme ceci:
la source
reinterpret_cast
n'est pas nécessaire