Quand je fais ça:
std::vector<int> hello;
Tout fonctionne très bien. Cependant, quand je fais un vecteur de références à la place:
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 aux structures dans un vecteur, pour ne pas avoir à me mêler des pointeurs Pourquoi le vecteur lance-t-il une crise à ce sujet? Est-ce que ma seule option est d'utiliser un vecteur de pointeurs?
Le type de composant des conteneurs, tels que 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 assignables ne sont pas non plus autorisés en tant que composants de conteneurs, par exemple. vector<const int>
n'est pas autorisé.
oui vous pouvez, cherchez std::reference_wrapper
, qui imite une référence mais qui est assignable et qui peut aussi être "réinstallé"
De par leur nature, les références ne peuvent être définies qu’au moment de leur création; c'est-à-dire que les deux lignes suivantes ont des effets très différents:
int & A = B; // makes A an alias for B
A = C; // assigns value of C to B.
De plus, c'est illégal:
int & D; // must be set to a int variable.
Cependant, lorsque vous créez un vecteur, il n’est pas possible d’attribuer des valeurs à ses éléments lors de la création. Vous ne faites en gros que le dernier exemple.
Ion Todirel a déjà mentionné une réponseOUIen utilisant std::reference_wrapper
. Depuis C++ 11 nous avons un mécanisme pour extraire un objet de std::vector
et supprimer la référence en utilisant std::remove_reference
. Vous trouverez ci-dessous un exemple compilé avec g++
et clang
avec option.-std=c++11
et exécuté avec succès.
#include <iostream>
#include <vector>
#include<functional>
class MyClass {
public:
void func() {
std::cout << "I am func \n";
}
MyClass(int y) : x(y) {}
int getval()
{
return x;
}
private:
int x;
};
int main() {
std::vector<std::reference_wrapper<MyClass>> vec;
MyClass obj1(2);
MyClass obj2(3);
MyClass& obj_ref1 = std::ref(obj1);
MyClass& obj_ref2 = obj2;
vec.Push_back(obj_ref1);
vec.Push_back(obj_ref2);
for (auto obj3 : vec)
{
std::remove_reference<MyClass&>::type(obj3).func();
std::cout << std::remove_reference<MyClass&>::type(obj3).getval() << "\n";
}
}
boost::ptr_vector<int>
fonctionnera.
Edit: suggère d'utiliser std::vector< boost::ref<int> >
, ce qui ne fonctionnera pas car vous ne pouvez pas construire par défaut un boost::ref
.
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 aboutirait à l'adresse de l'objet référencé et vous ne pouvez donc jamais obtenir un pointeur sur une référence. std::vector
fonctionne avec des pointeurs sur ses éléments, donc les valeurs stockées doivent pouvoir être pointées. Vous devrez utiliser des pointeurs à la place.
Comme d'autres l'ont mentionné, vous utiliserez probablement plutôt un vecteur de pointeurs.
Cependant, vous pouvez utiliser un ptr_vector à la place!
Utilisez std::reference_wrapper
comme ceci:
#include <functional>
#include <string>
#include <vector>
#include <iostream>
int main()
{
std::string hello = "Hello, ";
std::string world = "everyone!";
typedef std::vector<std::reference_wrapper<std::string>> vec_t;
vec_t vec = {hello, world};
vec[1].get() = "world!";
std::cout << hello << world << std::endl;
return 0;
}
Comme standard suggère , pour un conteneur standard X
contenant des objets de type T
name__, T
doit être Erasable
de X
name__.
Erasable
signifie que l'expression suivante est bien formée:
allocator_traits<A>::destroy(m, p)
A
est le type d'allocateur du conteneur, m
est une instance d'allocateur et p
est un pointeur de type *T
. Voir ici pour la définition de Erasable
name__.
Par défaut, std::allocator<T>
est utilisé comme allocateur de vecteur. Avec l'allocateur par défaut, l'exigence est équivalente à la validité de p->~T()
(notez que T
est un type de référence et p
est un pointeur sur une référence). Cependant, le pointeur sur une référence est illégal , par conséquent l'expression n'est pas bien formée.
Comme le suggèrent les autres commentaires, vous ne pouvez utiliser que des pointeurs . Mais si cela vous aide, voici une technique pour éviter de vous confronter directement aux pointeurs.
Vous pouvez faire quelque chose comme ce qui suit:
vector<int*> iarray;
int default_item = 0; // for handling out-of-range exception
int& get_item_as_ref(unsigned int idx) {
// handling out-of-range exception
if(idx >= iarray.size())
return default_item;
return reinterpret_cast<int&>(*iarray[idx]);
}