Wenn ich das mache:
std::vector<int> hello;
Alles funktioniert super Wenn ich jedoch stattdessen einen Vektor von Referenzen mache:
std::vector<int &> hello;
Ich bekomme schreckliche Fehler wie
fehler C2528: 'Zeiger': Zeiger auf Verweis ist ungültig
Ich möchte eine Reihe von Referenzen auf Strukturen in einen Vektor setzen, damit ich mich nicht mit Zeigern beschäftigen muss. Warum wirft der Vektor darüber einen Wutanfall auf? Ist meine einzige Möglichkeit, stattdessen einen Vektor von Zeigern zu verwenden?
Der Komponententyp von Containern wie Vektoren muss zuweisbar sein. Referenzen können nicht zugewiesen werden (Sie können sie nur einmal initialisieren, wenn sie deklariert sind, und Sie können sie später nicht auf etwas anderes verweisen). Andere nicht zuweisbare Typen sind ebenfalls nicht als Komponenten von Containern zulässig, z. vector<const int>
ist nicht erlaubt.
ja, du kannst nach std::reference_wrapper
suchen, das eine Referenz nachahmt, aber zuweisbar ist und auch "reseating"
Referenzen können naturgemäß nur zum Zeitpunkt ihrer Erstellung gesetzt werden; die folgenden zwei Zeilen haben sehr unterschiedliche Wirkungen:
int & A = B; // makes A an alias for B
A = C; // assigns value of C to B.
Des weiteren ist das illegal:
int & D; // must be set to a int variable.
Wenn Sie jedoch einen Vektor erstellen, können Sie den Elementen bei der Erstellung keine Werte zuweisen. Sie machen im Wesentlichen nur eine ganze Reihe des letzten Beispiels.
Ion Todirel erwähnte bereits eine AntwortYESmit std::reference_wrapper
. Seit C++ 11 haben wir einen Mechanismus, um ein Objekt aus std::vector
abzurufen und die Referenz mit std::remove_reference
zu entfernen. Unten ist ein Beispiel angegeben, das mit g++
und clang
mit der Option kompiliert wurde-std=c++11
und erfolgreich ausgeführt.
#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>
wird funktionieren.
Edit: war ein Vorschlag zur Verwendung von std::vector< boost::ref<int> >
, der nicht funktioniert, da Sie keinen boost::ref
standardmäßig erstellen können.
Es ist ein Fehler in der C++ - Sprache. Sie können die Adresse einer Referenz nicht verwenden, da dies zu einem Verweis auf die Adresse des Objekts führen würde, sodass Sie niemals einen Zeiger auf eine Referenz erhalten können. std::vector
arbeitet mit Zeigern auf seine Elemente, so dass auf die gespeicherten Werte verwiesen werden muss. Sie müssen stattdessen Zeiger verwenden.
Wie bereits erwähnt, werden Sie wahrscheinlich stattdessen einen Zeigervektor verwenden.
Möglicherweise möchten Sie jedoch die Verwendung eines ptr_vector in Betracht ziehen!
Verwenden Sie std::reference_wrapper
wie folgt:
#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;
}
Wie Standard schlägt vor für einen Standardcontainer X
, der Objekte des Typs T
enthält, muss T
Erasable
von X
sein.
Erasable
bedeutet, dass der folgende Ausdruck gut geformt ist:
allocator_traits<A>::destroy(m, p)
A
ist der Zuordnungstyp des Containers, m
ist die Zuordnungsinstanz und p
ist ein Zeiger vom Typ *T
. Siehe hier für die Definition von Erasable
.
Standardmäßig wird std::allocator<T>
als Allokator des Vektors verwendet. Bei der Standardzuweisung entspricht die Anforderung der Gültigkeit von p->~T()
(Beachten Sie, dass T
ein Referenztyp und p
ein Zeiger auf eine Referenz ist). Jedoch Zeiger auf eine Referenz ist illegal , daher ist der Ausdruck nicht gut geformt.
Wie aus den anderen Kommentaren hervorgeht, sind Sie auf die Verwendung von Zeigern beschränkt. Wenn dies jedoch hilfreich ist, können Sie die direkte Verwendung von Zeigern vermeiden.
Sie können etwas wie das Folgende tun:
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]);
}