Von shared_ptr nach ptr_vector



  • otze schrieb:

    Darf man die überhaupt in einen vector stecken?

    natürlich, unique_ptr ist auto_ptr richtig gemacht... 😉

    otze schrieb:

    Immerhin sind die non-copyable und non-assignable.

    Aber sie sind moveable. 😉

    otze schrieb:

    D.h. ein simples push_back() kann alles kaputt machen.

    Nope, funktioniert problemlos.



  • dot schrieb:

    otze schrieb:

    Immerhin sind die non-copyable und non-assignable.

    Aber sie sind moveable. 😉

    Ahh C++11 mal wieder. Ich hatte noch std::tr1::unique_ptr aus C++03 im Kopf 😉



  • Alf1979 schrieb:

    Vielen dank für die antworten. Angeregt durch eure antworten bin ich auch zu dem schluss gekommen, dass es blödsinn ist, was ich vorhabe, da die o.g. besitzverhältnisse existieren, bzw. eben die objekte gelöscht werden.

    Ich werde mein konstrukt auf einen std::vector mit shared_ptr umbauen.

    Was für Besitzverhältnisse existieren denn in deiner Anwendung da genau? Wieso müssen mehrere Objekte den Besitz dieser Dinge, die du da in den vector packen willst, teilen?



  • Naja, teilen ... es ist einfach eine vorgabe der entwicklungsleitung meiner firma, da hat es geheißen: "verwendet smart pointer".

    Und da ich bei boost die wahl zwischen scoped_ptr und shared_ptr habe, habe ich mich für shared_ptr entschieden.

    Wenn ich mich nicht irre, wäre unique_ptr die bessere wahl, aber der c++11 standard wird bei uns erst in ca. 1 bis 1,5 jahren einzug erhalten.



  • Oh, das ist schade, shared_ptr ist eigentlich in der Regel keine gute Wahl, denn shared Ownerschip braucht man am besten nie und shared_ptr ist ein ziemliches Schwergewicht...
    Ich würde an deiner Stelle eher versuchen, std::auto_ptr zu verwenden. Dann eben zusammen mit boost::ptr_vector.



  • Ja, wenn du nur etwas brauchst um kurzfristig ein gerade erzeugtes Objekt zu speichern, dann ist auto_ptr deine beste Wahl. Dann ist auch klar, dass damit der Besitz transferiert wird.



  • otze schrieb:

    Ich hatte noch std::tr1::unique_ptr aus C++03 im Kopf 😉

    Das gibt's doch gar nicht. Und TR1 ist auch nicht in C++03 drin.



  • Welche Gründe gibt es für euch nach für die Verwendung von boost::ptr_vector<T>?

    Also generell fand ich es immer schön, dass man bei Iterieren gleich eine Referenz hatte und keinen Pointer, aber das ist ja eigentlich kein Grund diese zusätzliche Library im Programm zu verwenden.
    Zudem konnte man bestimmen, wie die Elemente in dem vector geclont werden sollen...
    Naja... Aber auch das ist auch irgendwie nicht das richtig überzeugende Argument für mich. So oft brauch man es auch nicht und so ne kleine Funktion ist schnell geschrieben.

    Sterben die Pointer-Container bald aus oder welche Argumente habt ihr für die Verwendung der Pointer-Container?

    Gruß,
    XSpille



  • Obwohl ich den vector<unique_ptr<T>> weniger schön als ptr_vector finde, verzichte ich aufgrund der Abhängigkeit zu Boost darauf.

    Dabei hat ein ptr_vector so viele Vorteile:

    • Schönere Syntax, bzw. einheitliche Syntax zu einem pointerlosen Container
    • Kopierbar
    • Sortierbar (sort auf vector<unique_ptr<T>> vergleicht deren Speicherposition)
    • Allgemein für STL Algorithmen geeignet, bei vector<unique_ptr<T>> muss man boost::indirect_iterator verwenden und dann hat man wieder eine (wenn auch minimale) Boost-Abhängigkeit


  • Danke für die vielen antworte.

    Was mir aufgefallen ist, etwas weiter oben habe ich den hinweis bekommen, auto_ptr zu verwenden: boost::ptr_vector<std::auto_ptr<T>>

    Aber das kann doch gar nicht funktionieren, oder? Da auto_ptr nicht zusammen mit std::vector verwendet werden kann, und boost::ptr_vector baut doch auch auf std::vector auf?



  • Alf1979 schrieb:

    Aber das kann doch gar nicht funktionieren, oder? Da auto_ptr nicht zusammen mit std::vector verwendet werden kann, und boost::ptr_vector baut doch auch auf std::vector auf?

    Du darfst keinen std::vector<std::auto_ptr<T> > machen, genau darum gibt es boost::ptr_vector ja überhaupt erst. Du sollst auch keinen boost::ptr_vector<std::auto_ptr<T> > machen, sondern du willst sowohl boost::ptr_vector als auch std::auto_ptr verwenden. auto_ptr zum Rumreichen von Objekten an den neuen Besitzer, ptr_vector zum Halten deiner mit new erzeugen Instazen. Wobei ich mir an deiner Stelle sowieso erst mal überlegen würde, ob der Besitzwechsel überhaupt notwendig und sinnvoll ist, oder ob ich nicht ein besseres Design finden kann, wo die Objekte auch dort zerstört werden, wo sie erzeugt wurden und eigentlich maximal ein ptr_vector oder so ausreicht...

    lanzenwerfer schrieb:

    Dabei hat ein ptr_vector so viele Vorteile:

    • Schönere Syntax, bzw. einheitliche Syntax zu einem pointerlosen Container
    • Kopierbar
    • Sortierbar (sort auf vector<unique_ptr<T>> vergleicht deren Speicherposition)
    • Allgemein für STL Algorithmen geeignet, bei vector<unique_ptr<T>> muss man boost::indirect_iterator verwenden und dann hat man wieder eine (wenn auch minimale) Boost-Abhängigkeit

    Lambdas machens besser ;). Abgesehen davon, find ich Move Semantik hier viel sauberer und bevorzuge std::vector<std::unique_ptr<T>> schon allein wegen der Konsistenz mit dem Rest der STL...



  • Alf1979 schrieb:

    Was mir aufgefallen ist, etwas weiter oben habe ich den hinweis bekommen, auto_ptr zu verwenden: boost::ptr_vector<std::auto_ptr<T>>

    Aber das kann doch gar nicht funktionieren, oder? Da auto_ptr nicht zusammen mit std::vector verwendet werden kann, und boost::ptr_vector baut doch auch auf std::vector auf?

    Das hast du falsch verstanden. Es war so gemeint:

    auto_ptr<int> quelle();
    
    int main()
    {
      ptr_vector<int> v;     // <-- nix mit auto_ptr
      v.push_back(quelle()); // <-- ptr_vector befreit und übernimmt den rohen
                             //     Zeiger aus dem auto_ptr (ownership transfer)
    }
    


  • dot schrieb:

    [...] Abgesehen davon, find ich Move Semantik hier viel sauberer und bevorzuge std::vector<std::unique_ptr<T>> schon allein wegen der Konsistenz mit dem Rest der STL...

    Warum man vielleicht doch einen ptr_vector benutzen möchte:

    template<class T, class...Args>
    unique_ptr<T> make_unique(Args&&...args)
    {
       unique_ptr<T> p (new T(forward<Args>(args)...));
       return p;
    }
    
    void oops(vector<unique_ptr<int>> const& v)
    { //                              ^^^^^
       if (!p.empty())
          *v[0] = 99; // klappt trotzdem, da unique_ptr const nicht propagiert
       // ^
       // Extra Dereferenzierung nervt
    }
    
    int main()
    {
       vector<unique_ptr<int>> v;
       v.push_back(make_unique<int>(23));
       oops(v);
       cout << *v[0] << endl;
       //      ^
       // Extra Dereferenzierung nervt
    }
    

Anmelden zum Antworten