451 Stimmen

Warum kann ich keinen Vektor von Referenzen erstellen?

Wenn ich das tue:

std::vector<int> hello;

Alles funktioniert bestens. Allerdings, wenn ich es ein Vektor von Referenzen statt:

std::vector<int &> hello;

Ich erhalte schreckliche Fehler wie

Fehler C2528: 'pointer' : Zeiger auf Referenz ist illegal

Ich möchte eine Reihe von Verweisen auf structs in einen Vektor zu setzen, so dass ich nicht mit Zeigern zu mischen haben. Warum ist vector wirft einen Wutanfall über diese? Ist meine einzige Möglichkeit, stattdessen einen Vektor von Zeigern zu verwenden?

54 Stimmen

Können Sie std::vector<reference_wrapper<int> > hello verwenden; siehe informit.com/guides/content.aspx?g=cplusplus&seqNum=217

7 Stimmen

@amit der Link ist nicht mehr gültig, offizielle Dokumentation aquí

430voto

newacct Punkte 114757

Der Komponententyp von Containern wie Vektoren muss sein zuordenbar . Referenzen sind nicht zuweisbar (sie können nur einmal initialisiert werden, wenn sie deklariert werden, und sie können später nicht auf etwas anderes verweisen). Andere nicht zuweisbare Typen sind ebenfalls nicht als Komponenten von Containern erlaubt, z.B. vector<const int> ist nicht erlaubt.

1 Stimmen

Wollen Sie damit sagen, dass ich keinen Vektor von Vektoren haben kann? (Ich bin sicher, dass ich das schon getan habe...)

11 Stimmen

Ja, ein std::vector< std::vector<int> > ist korrekt, std::vector ist zuweisbar.

20 Stimmen

Dies ist in der Tat der "eigentliche" Grund. Der Fehler, dass T* nicht aus T ist U& sein kann, ist nur ein Nebeneffekt der verletzten Anforderung, dass T zuweisbar sein muss. Wenn vector in der Lage wäre, den Typparameter genau zu überprüfen, dann würde er wahrscheinlich sagen "violated requirement: T& nicht zuweisbar"

157voto

Ja, das können Sie, suchen Sie nach std::reference_wrapper der eine Referenz nachahmt, aber zuweisbar ist und auch "neu platziert" werden kann

4 Stimmen

Gibt es eine Möglichkeit, den Anruf zu umgehen? get() wenn ich versuche, auf eine Methode einer Instanz einer Klasse in diesem Wrapper zuzugreifen? z.B.. reference_wrapper<MyClass> my_ref(...); my_ref.get().doStuff(); ist nicht sehr referenzartig.

3 Stimmen

Ist es nicht implizit castable auf den Typ selbst durch die Rückgabe der Referenz?

4 Stimmen

Ja, aber das erfordert einen Kontext, der andeutet, welche Umwandlung erforderlich ist. Beim Mitgliederzugriff ist das nicht der Fall, daher die Notwendigkeit von .get() . Was timdiels will ist operator. Die neuesten Vorschläge/Diskussionen dazu sind hier zu finden.

43voto

James Curran Punkte 98228

Es liegt in der Natur der Sache, dass Referenzen nur zu dem Zeitpunkt gesetzt werden können, zu dem sie erstellt werden, d.h. die beiden folgenden Zeilen haben sehr unterschiedliche Auswirkungen:

int & A = B;   // makes A an alias for B
A = C;         // assigns value of C to B.

Außerdem ist dies illegal:

int & D;       // must be set to a int variable.

Wenn Sie jedoch einen Vektor erstellen, gibt es keine Möglichkeit, den Elementen bei der Erstellung Werte zuzuweisen. Sie machen im Grunde nur einen ganzen Haufen des letzten Beispiels.

11 Stimmen

"Wenn Sie einen Vektor erstellen, gibt es keine Möglichkeit, seinen Elementen bei der Erstellung Werte zuzuweisen" Ich verstehe nicht, was Sie mit dieser Aussage meinen. Was sind "seine Elemente bei der Erstellung"? Ich kann einen leeren Vektor erstellen. Und ich kann Elemente mit .push_back() hinzufügen. Sie weisen nur darauf hin, dass Referenzen nicht standardmäßig konstruierbar sind. Aber ich kann durchaus Vektoren von Klassen haben, die nicht standardmäßig konstruierbar sind.

4 Stimmen

Das Element ype von std::vector<T> muss nicht standardmäßig konstruierbar sein. You can write struct A { A(int); private: A(); }; vector<A> a; problemlos schreiben - solange Sie keine Methoden verwenden, die eine Standard-Konstruierbarkeit erfordern (wie v.resize(100); - stattdessen müssen Sie v.resize(100, A(1)); verwenden)

0 Stimmen

Und wie würden Sie ein solches push_back() in diesem Fall schreiben? Es wird immer noch Zuweisung, nicht Konstruktion verwenden.

35voto

Steephen Punkte 12939

Ion Todirel hat bereits eine Antwort gegeben YES mit std::reference_wrapper . Seit C++11 haben wir einen Mechanismus zum Abrufen von Objekten aus std::vector und entfernen Sie den Verweis, indem Sie std::remove_reference . Im Folgenden wird ein Beispiel aufgeführt, das mit g++ y clang mit Option -std=c++11 und erfolgreich durchgefü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";
        }             
    }

19 Stimmen

Ich sehe den Wert nicht in std::remove_reference<> hier. Der Punkt der std::remove_reference<> ist es, Ihnen zu erlauben, "den Typ T zu schreiben, aber ohne eine Referenz zu sein, wenn es eine ist". Also std::remove_reference<MyClass&>::type ist genau dasselbe wie das Schreiben MyClass .

3 Stimmen

Das hat überhaupt keinen Wert - Sie können einfach schreiben for (MyClass obj3 : vec) std::cout << obj3.getval() << "\n"; (oder for (const MyClass& obj3: vec) wenn Sie erklären, dass getval() const, wie Sie sollten).

20voto

Adam Rosenfield Punkte 373807

Das ist ein Fehler in der Sprache C++. Man kann die Adresse eines Verweises nicht übernehmen, da der Versuch, dies zu tun, zur Adresse des Objekts führen würde, auf das verwiesen wird, und somit kann man niemals einen Zeiger auf einen Verweis erhalten. std::vector arbeitet mit Zeigern auf seine Elemente, daher müssen die gespeicherten Werte mit einem Zeiger versehen werden können. Sie werden stattdessen Zeiger verwenden müssen.

0 Stimmen

Ich denke, es könnte mit einem void * Puffer und Platzierung neu implementiert werden. Nicht, dass dies viel Sinn machen würde.

61 Stimmen

"Fehler in der Sprache" ist zu stark. Das ist Absicht. Ich glaube nicht, dass es erforderlich ist, dass Vektoren mit Zeigern auf Elemente arbeiten. Es ist jedoch erforderlich, dass das Element zuweisbar ist. Referenzen sind es nicht.

0 Stimmen

Sie können nicht die sizeof auch keine Referenz.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X