[vector] Referenz auf eine Element?



  • Hi,

    ich hab eine Template-Klasse MyList<T> geschrieben, die einen vector<T> enthält. Nun habe ich eine Funktion geschrieben, mit der ich die Referenz T& auf eine Element des vector haben möchte:

    // m_vList ist der vector<T>
    template <class T>
    T& MyList<T>::getElement(int nIndex) const
    {
    	if (nIndex<0) return NULL;
    	LIST::size_type	i = nIndex;
    	if (i<m_vList.size()) return m_vList.at(i);
    	else return NULL;
    }
    

    Damit bekomme ich für die return-Anweisungen Fehler.
    Was kann ich tun, um eine Referenz zurückzubekommen? 😕



  • Referenzen können nicht NULL sein. Du musst dir etwas anderes überlegen, das passieren soll, wenn der Index ungültig ist. Du könntest z.B. die Prüfung mit size weglassen, und damit die Exception, die vector::at wirft, weiterreichen. Oder du könntest eine Referenz auf ein statisches Objekt zurückgeben.



  • statt NULL zurückzugeben müsstest du eine Exception werfen.

    Und die Referenz ist nur solange gültig, solange der Vector nicht wächst,
    danach kann da was völlig anderes sein.

    Devil



  • Ok, dann wäre immer noch der folgende Fehler übrig:

    error C2440: 'return': 'const std::allocator<_Ty>::value_type' kann nicht in 'MyElem &' konvertiert werden
    with
    [
    _Ty=MyElem
    ]

    Wie löse ich das Problem. Wenn ich es richtig verstanden hab, gibt at() eine Referenz zurück, aber der Compiler kriegt die Konvertierung nicht hin. 😕



  • don_basto schrieb:

    Wie löse ich das Problem. Wenn ich es richtig verstanden hab, gibt at() eine Referenz zurück, aber der Compiler kriegt die Konvertierung nicht hin.

    Wenn du ohnehin selber den Index prüfst brauchst du kein at() zu verwenden, op[] tut's auch.
    Und was du vorhast wäre sowieso keine gute Idee (du umgehst das logische const der MyList<T>), mach's gleich richtig:

    // Referenz für non-const
    template <class T>
    T& MyList<T>::getElement(int nIndex);
    
    // Kopie (ggf const Referenz) für const
    template <class T>
    T MyList<T>::getElement(int nIndex) const;
    


  • Mir geht's um folgendes Problem:

    // Definition in MyList.h
    template <class T>
    T& MyList<T>::getElement(int nIndex) const
    {
       return _List.at(i);
    }
    
    // MyList hat ein Attribut _list
    MyList<MyElem> myList;
    
    // das geht
    MyElem tmp = myList._list.at(0);
    
    // das geht nicht 
    MyElem tmp2 = myList.getElement(0);
    

    Weiss jemand, woran das liegt bzw. wie komme ich an die Referenz heran?



  • don_basto schrieb:

    Weiss jemand, woran das liegt

    getElement ist const. Du kannst damit also keine nicht-const-Referenz rausgeben, wenn du nicht das const rauscastest oder mutable benutzt. Beides solltest du aber nicht nur deshalb machen, damit dein Code so funktioniert.



  • don_basto schrieb:

    Weiss jemand, woran das liegt ...

    Am const.



  • Thx, 🙂
    das isses. Ich kapier es nur nicht ganz. Ich dacht, das const-Methoden bedeuten, dass man sie auch auf const-Objekte anwenden kann, weil diese eben das Objekt nicht ändern. Wenn ich eine Referenz zurückgebe, ändere ich am Objekt ja erstmal nix. 😕
    Auf der anderen Seite sind in einem const-Objekt alle Attribute konstant, also warum eigentlich eine normale Referenz zurückgeben. Die Lösung wäre dann wohl folgende:

    T&		getElement(int nIndex);
    const T&	getElement(int nIndex) const;
    

    Falls ich falsch liege, bitte korrigieren.



  • [offtopic]
    noch eleganter fände ich operator überladung
    http://www.cpp-tutor.de/cpp/le12/le12_05.htm#index_op



  • don_basto schrieb:

    Ich dacht, das const-Methoden bedeuten, dass man sie auch auf const-Objekte anwenden kann

    Und nur auf konstante Objekte.

    don_basto schrieb:

    Wenn ich eine Referenz zurückgebe, ändere ich am Objekt ja erstmal nix.

    Direkt nicht, aber du schaffst damit die Möglichkeit dies zu tun.
    Das ist so, wie wenn du deinen Haustürschlüssel stecken lässt. Du selbst hast zwar niemanden zum Einbruch angestiftet, hast aber alle Voraussetzungen dafür geschaffen.

    don_basto schrieb:

    Auf der anderen Seite sind in einem const-Objekt alle Attribute konstant, also warum eigentlich eine normale Referenz zurückgeben. Die Lösung wäre dann wohl folgende:

    T&		getElement(int nIndex);
    const T&	getElement(int nIndex) const;
    

    Yep, das Prinzip ist richtig. Operator [] wird idR auf die gleiche Weise implementiert.



  • groovemaster schrieb:

    don_basto schrieb:

    Ich dacht, das const-Methoden bedeuten, dass man sie auch auf const-Objekte anwenden kann

    Und nur auf konstante Objekte.

    Bisher hat folgender Kode funktioniert. Hängt vielleicht von der Art der Rückgabe (Wert bzw. Referenz).

    // MyClass
    int getID() const;
    
    // Init
    MyClass cNormal;
    const MyClass cKonstant = cNormal;
    int nID;
    
    // Aufruf, sollte beides funktionieren
    nID = cNormal.getID();
    nID = cKonstant.getID();
    


  • don_basto schrieb:

    Bisher hat folgender Kode funktioniert. Hängt vielleicht von der Art der Rückgabe (Wert bzw. Referenz).

    Ja, sry. Kam im Zusammenhang etwas falsch rüber. Ich meinte eigentlich, dass du auf const Objekte auch nur const Methoden anwenden kannst.


Anmelden zum Antworten