Verweis uaf eine gelöschte Funktion in std::unique_ptr



  • Quaneu schrieb:

    Entschuldige Du hast recht, das Beispiel war falsch. Hatte es mit items.at() ausprobiert. Und da geht es nicht, wenn man sich zweimal den selben Eintrag holt.

    Auch das ist Blödsinn.



  • Kommt eben drauf an wie man sich den Eintrag holt.

    auto &a = items.at(0); // Geht zweimal
    auto a = std::move(items.at(0)); // Geht nicht zweimal
    


  • Ich halte es eher so, daß ich versuche, einen unique_ptr gar nicht erst aus meiner Klasse heraus zu geben, außer wenn tatsächlich ein Besitz-Transfer stattfinden soll.

    Die Regel wäre etwa folgende:

    • Der Besitzer des unique_ptr ist ALLEINIGER Besitzer des Objekts
    • Sollen keine anderen Objekte die betreffenden Objekte besitzen dürfen, wird ein raw-pointer zurückgegeben
    • raw-pointer sind weak-pointer, garantieren also keinen Besitz über das betreffende Objekt
    • Sollen andere Objekte ebenfalls Besitz übernehmen können, sollte ein shared_ptr verwendet werden

    Hatte allerdings glaube ich noch nicht den Fall, daß ich eine komplette Objektliste aus unique pointern zurückgeben musste.
    Theoretisch kann man da eine zweite Liste aus raw-pointern in der Klasse speichern und die dann anstatt der unique_ptr Liste zurückgeben, aber arg schön ist das auch nicht. Da würde ich dann eher zu shared pointern tendieren. Wenn dein Code nicht nur über die Liste iteriert, sondern auch mal ein Objekt aus der Liste irgendwo anders abspeichern will wäre das eh die bessere Wahl.



  • Quaneu schrieb:

    Kommt eben drauf an wie man sich den Eintrag holt.

    auto &a = items.at(0); // Geht zweimal
    auto a = std::move(items.at(0)); // Geht nicht zweimal
    

    Wiso willst du das item raus nehmen?
    Wenn es nur benötigt wird um daten aus dem element zu lesen reicht es über die referenz da muss nichts kopiert/gemoved werden



  • Quaneu schrieb:

    Kommt eben drauf an wie man sich den Eintrag holt.

    auto &a = items.at(0); // Geht zweimal
    auto a = std::move(items.at(0)); // Geht nicht zweimal
    

    Unteres kompiliert nicht einmal. Ergo: Blödsinn.

    Grund: du hast aus deiner Funktion eine const-ref zurückgegeben.

    Außerdem: wenn das jetzt nicht const wäre, hättest du ja explizit mit std::move aufgefordert, den Originalwert zu ändern. Dann wärst du selbst schuld.



  • Quaneu schrieb:

    Mittlerweile zweifel ich jedoch grundsätzlich an der Verwendung von unique_ptr in einem Vector, wenn dieser nach außen gegeben wird...

    Einfache Pointer sind da auch nicht unbedingt besser: man kann delete aufrufen oder den Wert ändern.
    Getter/Setter werden sowieso viel zu exzessiv verwendet. Man sollte dann aber wenigstens keinen Zugriff auf die Innereien haben (wie in deinem Fall).
    Wenn du keine Nullpointer in deinem Vector hast, könnte man da was mit boost löten und Iteratoren auf konstante Referenzen statt einem kompletten Vector ausliefern:

    #include <iostream>
    #include <vector>
    #include <memory>
    #include <algorithm>
    #include <boost/iterator/indirect_iterator.hpp>
    
    int main()
    {
      std::vector<std::unique_ptr<int>> v;
      v.emplace_back(new int{1});
      v.emplace_back(new int{2});
    
      boost::indirect_iterator<decltype(v.begin()), const int&> 
        indirect_first(v.begin()), indirect_last(v.end());
    
      std::copy(indirect_first, indirect_last, std::ostream_iterator<int>(std::cout, ","));
    
      std::cout << std::endl;  
    }
    

Anmelden zum Antworten