Warum kann ich keinen Referenzvektor erstellen?

Lesezeit: 7 Minuten

Warum kann ich keinen Referenzvektor erstellen
Colen

Wenn ich das mache:

std::vector<int> hello;

Alles funktioniert super. Wenn ich es jedoch stattdessen zu einem Vektor von Referenzen mache:

std::vector<int &> hello;

Ich bekomme schreckliche Fehler wie

Fehler C2528: ‘Zeiger’: Zeiger auf Referenz ist ungültig

Ich möchte eine Reihe von Verweisen auf Strukturen in einen Vektor einfügen, damit ich mich nicht mit Zeigern herumschlagen muss. Warum bekommt Vector deswegen einen Wutanfall? Ist meine einzige Möglichkeit, stattdessen einen Zeigervektor zu verwenden?

1647157809 668 Warum kann ich keinen Referenzvektor erstellen
neues Konto

Der Komponententyp von Containern wie Vektoren muss sein zuordenbar. Referenzen sind nicht zuweisbar (Sie können sie nur einmal initialisieren, wenn sie deklariert sind, und Sie können sie später nicht auf etwas anderes verweisen). Auch andere nicht zuordenbare Typen sind als Bestandteile von Containern nicht zulässig, z vector<const int> ist nicht erlaubt.

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

    – James Curran

    28. Mai 2009 um 18:29 Uhr

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

    – Martin Côte

    28. Mai 2009 um 18:31 Uhr

  • In der Tat ist dies der “eigentliche” Grund. Der Fehler, dass T* unmöglich von T ist U& ist, ist nur ein Nebeneffekt der verletzten Anforderung, dass T zuweisbar sein muss. Wenn vector den Typparameter genau überprüfen könnte, würde es wahrscheinlich sagen “verletzt Anforderung: T& nicht zuweisbar”

    – Johannes Schaub – litb

    28. Mai 2009 um 18:47 Uhr

  • Überprüfung des zuordenbaren Konzepts bei boost.org/doc/libs/1_39_0/doc/html/Assignable.html Alle Operationen außer dem Swap sind auf Referenzen gültig.

    – amit kumar

    18. August 2009 um 16:01 Uhr

  • Dies ist nicht mehr wahr. Seit C++11 ist die einzige betriebsunabhängige Anforderung für das Element, „Löschbar“ zu sein, und die Referenz ist es nicht. Siehe stackoverflow.com/questions/33144419/….

    – See9m

    14. Juli 2018 um 7:02 Uhr


Ja, das kannst du, suchen std::reference_wrapperdas eine Referenz nachahmt, aber zuweisbar ist und auch “neu eingesetzt” werden kann

  • Gibt es eine Möglichkeit, das Telefonieren zu umgehen? get() zuerst beim Versuch, 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 Referenz wie.

    – Tim Diels

    17. Oktober 2014 um 15:40 Uhr

  • Ist es nicht implizit auf den Typ selbst umsetzbar, indem die Referenz zurückgegeben wird?

    – WorldSEnder

    13. November 2014 um 12:52 Uhr

  • Ja, aber das erfordert einen Kontext, der impliziert, welche Konvertierung erforderlich ist. Der Mitgliederzugriff tut dies nicht, daher die Notwendigkeit für .get(). Was timdies will ist operator.; werfen Sie einen Blick auf die neuesten Vorschläge/Diskussionen darüber.

    – Unterstrich_d

    30. September 2018 um 12:50 Uhr

  • Beachten Sie jedoch, dass während reference_wrapper Im Gegensatz zum rohen Referenztyp, der “neu eingesetzt” werden kann, kann er immer noch nicht nicht initialisiert werden, sodass er nicht standardmäßig konstruierbar ist. Das heißt, man kann zwar konstruieren vector<reference_wrapper<int>>{int1, int2, int3}man kann immer noch keinen Vektor mit mit standardmäßig konstruierten Elementen haben: vector<reference_wrapper<int>>(5). Dies wird nicht einmal von IDE (CLion) abgefangen, schlägt jedoch bei der Kompilierung fehl.

    – Iwan

    14. Oktober 2020 um 7:42 Uhr


  • Ich finde es seltsam, dass dies in deklariert ist <functional> — es scheint allgemeiner zu sein als nur aufrufbare Objekte.

    – wcochran

    27. Mai 2021 um 14:56 Uhr

Warum kann ich keinen Referenzvektor erstellen
James Curran

Referenzen können naturgemäß nur zum Zeitpunkt ihrer Erstellung gesetzt werden; dh die folgenden beiden 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, seinen Elementen bei der Erstellung Werte zuzuweisen. Sie machen im Wesentlichen nur eine ganze Menge des letzten Beispiels.

1647157809 213 Warum kann ich keinen Referenzvektor erstellen
Stefan

Ion Todirel erwähnte bereits eine Antwort JAWOHL verwenden std::reference_wrapper. Seit C++11 Wir haben einen Mechanismus zum Abrufen von Objekten std::vector und entfernen Sie den Verweis mit std::remove_reference. Nachfolgend finden Sie ein Beispiel, das mit kompiliert wurde g++ und clang mit Möglichkeit
-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";
    }             
}

Warum kann ich keinen Referenzvektor erstellen
ivaigult

TL; DR

Verwenden std::reference_wrapper so was:

#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;
}

Demo

Lange Antwort

Als Standard schlägt vorfür einen Standardcontainer X Objekte des Typs enthalten T, T muss sein Erasable von X.

Erasable bedeutet, dass der folgende Ausdruck wohlgeformt ist:

allocator_traits<A>::destroy(m, p)

A ist der Zuweisungstyp des Containers, m ist Zuweisungsinstanz und p ist ein Zeiger vom Typ *T. Sehen Hier zum Erasable Definition.

Standardmäßig, std::allocator<T> wird als Allokator des Vektors verwendet. Beim Default-Allokator ist die Anforderung gleichbedeutend mit der Gültigkeit von p->~T() (Beachten Sie das T ist ein Referenztyp und p ist ein Zeiger auf eine Referenz). Der Zeiger auf eine Referenz ist jedoch unzulässig, daher ist der Ausdruck nicht wohlgeformt.

1647157810 878 Warum kann ich keinen Referenzvektor erstellen
Adam Rosenfield

Es ist ein Fehler in der Sprache C++. Sie können die Adresse einer Referenz nicht übernehmen, da dies die Adresse des Objekts ergeben würde, auf das verwiesen wird, und Sie daher niemals einen Zeiger auf eine Referenz erhalten können. std::vector arbeitet mit Zeigern auf seine Elemente, daher muss auf die gespeicherten Werte verwiesen werden können. Sie müssen stattdessen Zeiger verwenden.

boost::ptr_vector<int> wird funktionieren.

Bearbeiten: war ein Anwendungsvorschlag std::vector< boost::ref<int> >was nicht funktioniert, da Sie a nicht standardmäßig erstellen können boost::ref.

  • Aber Sie können einen Vektor oder nicht standardmäßig konstruierbare Typen haben, richtig? Sie müssen nur darauf achten, nicht den Standardctor zu verwenden. des Vektors

    – Manuel

    4. Februar 2010 um 12:05 Uhr

  • @ Manuel: Oder resize.

    – Leichtigkeitsrennen im Orbit

    31. Juli 2014 um 11:00 Uhr

  • Seien Sie vorsichtig, die Pointer-Container von Boost übernehmen den exklusiven Besitz der Pointees. Zitieren: “Wenn Sie eine gemeinsame Semantik benötigen, ist diese Bibliothek nicht das, was Sie brauchen.”

    – Brandlingo

    6. März 2015 um 14:03 Uhr

996480cookie-checkWarum kann ich keinen Referenzvektor erstellen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy