"delete" Frage



  • Öhmm...nee ich glaube das meinte ich nicht...sondern ich meinte eher, wie es mit shared_ptr ausehen müsste?Weil mit den burschen hab ich noch net so viel erfahrung.



  • So?

    bewegungen.push_back( shared_ptr<Kontenbewegung>( new Kontenbewegung() ) );
    


  • Ok das hilft mir schonmal weiter, und die Deklaration vom vector wäre dann so hier?:

    std::vector< shared_ptr<Irgendwas> > vieles_irgendwas;
    

    ?



  • Sieht ok aus.



  • Und auf die deklaration kann ich dein push_back anwenden? Kann doch eigentlich bei deinem push_back das führende shared<> zeugs weglassen und nur ein normales new machen oder nicht?



  • OK hat sich erledigt, habs alleine hinbekommen. Aber mal ne andere Frage, worin besteht nun der Underschied zwischen auto_ptr und shared_ptr?also aufjedenfall schonmal die Containerkompatiblität, und das shared_ptr sich ums aufräumen kümmert, aber was noch?



  • Ok hab mir auch das ebend selbst beantwortet, danke für eure Beiträge.



  • Vielleicht kannst du dir auch mal Boost.Pointer Container anschauen, da werden die Zeiger auch automatisch freigegeben.



  • Alles klar Nexus, danke für den Hinweis, kannste eventuell kurz erklären wo der signifikanteste Unterschied liegt?



  • Die Pointer-Container speichern intern gerade Zeiger (wie könnte es anders sein ;)). Es existieren die analogen Container zur STL, wie ptr_vector , ptr_deque , ptr_list etc.

    Das führt zu verschiedenen Vorteilen für den Anwender:

    • Die gespeicherten Elemente müssen im Gegensatz zu STL-Containern nicht kopierkonstruierbar oder zuweisbar sein.
    • Bei Array-Containern wie boost::ptr_vector sind interne Operationen wie Löschungen und Einfügungen performanter, da nur Zeiger umgehängt werden.
    • Die Indirektion entfällt beim Aufruf. Man kann direkt schreiben vec[1] oder vec.front() , anstatt dass man noch einmal dereferenzieren muss.

    Siehe auch hier.

    P.S. Die ersten beiden Punkte beziehen sich auf den Vergleich zu STL-Containern mit Objekten, der dritte zu STL-Containern mit Smart-Pointern.



  • Klasse, ich danke, das sind ja fabelhafte Geschichten.Haste super erklärt.



  • David_pb schrieb:

    So?

    bewegungen.push_back( shared_ptr<Kontenbewegung>( new Kontenbewegung() ) );
    

    Das ist schlecht. Besser so:

    shared_ptr<Kontenbewegung> kbw(new Kontenbewegung());
    bewegungen.push_back(kbw);
    

    Begründung bitte selbst in der Boost Doku nachlesen, danke.



  • Danke hustbaer, habs mir mal durchgelesen.Mir ist aber noch nicht ganz klar was das im Bezug auf mein Konstrukt ausmacht.Ich hab mir mal das Beispiel aus der Boost Doku durchgelesen:

    void f(shared_ptr<int>, int);
    int g();
    
    void ok()
    {
        shared_ptr<int> p(new int(2));
        f(p, g());
    }
    
    void bad()
    {
        f(shared_ptr<int>(new int(2)), g());
    }
    

    Wenn ich das also richtig verstanden habe:

    Since function arguments are evaluated in unspecified order, it is possible for new int(2) to be evaluated first, g() second, and we may never get to the shared_ptr constructor if g throws an exception

    Das Funktionsargumente in keiner bestimmten Reihenfolge abgearbeitet werden können, und im Falle einer Exception wir niemals bei dem eigentlichen shared_ptr Konstrukt ankommen, ist das so richtig?Was bedeutet das aber in meinem Fall?

    bewegungen.push_back( shared_ptr<Kontenbewegung>( new Kontenbewegung() ) );
    

    Achso, es könnte also sein, das bei meiner erzeugung durch new eine Exception fliegt und ich dadurch nie bei shared_ptr ankomme?



  • wenn beim new eine Exception fliegt kann das aus zwei Gründen geschehen:

    1. Fehler bei der Speicherallokation. Der Konstruktor des Objektes wird daher nie aufgerufen, alles paletti (außer dass du ohne Speicher schlecht dastehst)

    2. Fehler im Ctor, dann werden die bereits konstruierten Teilobjekte wieder zerstört, die Exception fliegt und auch wieder kein Speicherleck - vorausgesetzt der Ctor ist exceptionsicher implementiert.

    Du kriegst durch ne Exception beim new also keine Speicherlecks
    Von der Exceptionsicherheit her kann man es also eigentlich als Einzeiler machen, wenns sich nur um einparametrige Funktionen handelt. Ob man sich das angewöhnen sollte und dann bei mehrparametrigen Funktionen immer dran denkt, es anders zu machen ist denke ich Geschmackssache. wirklich konsistent wäre es aber wohl nicht.



  • Ok, was heißt das aber nun bei mir? Warum hat hustbaer eine andere Variante empfohlen, die wie sie dem Boost Standard entspricht? Ich meine, wirkliche Probleme sehe ich jetzt nur bei der Übergabe an Funktionen, was aber ist das Problem bei meiner "push_backung"??

    1. Fehler bei der Speicherallokation. Der Konstruktor des Objektes wird daher nie aufgerufen, alles paletti (außer dass du ohne Speicher schlecht dastehst)

    Heißt das also, es kann passieren, das ich einen Null-Pointer in den Vector pushe, wenn dein Fall auftritt, und wird das push_back bei einem nicht-aufruf des Ctors abbgebrochen, wohl eher nicht,ne?



  • die begründung passt nicht auf dein beispiel.

    wie pumuckl schon gesagt und hustbaer es wohl gemeint hat, ist es eine sache der angewöhnung. wenn du es bei deiner einparametrigen funktion so machst, wie hustbaer vorschlägt, wirst du es bei allen anderen funktionen auch eher so machen. konsistenz und gewöhnung, das ist alles.



  • Ahhh alles klar, ok ich hatte gedacht das bezog sich jetzt wirklich spezifisch auf mein Problem. Super dann danke an alle.



  • Since function arguments are evaluated in unspecified order, it is possible for new int(2) to be evaluated first, g() second, and we may never get to the shared_ptr constructor if g throws an exception

    Verstehe ich nicht, die Argumente werden doch gleich komplett ausgewertet und nicht halb das erste, dann halb das zweite, dann die zweite Hälfte vom ersten?
    Dann sehe ich hierbei f( shared_ptr<int>(new int(2)), g() ); irgendwie kein Problem, da bei einer Exception von g() ja der shared_ptr , falls schon konstruiert, einfach destruiert wird. Ist hier evtl der Fall gemeint, dass das new nicht von einem shared_ptr ummantelt ist? Also f( new int(2), g() ); , wobei dann implizit der shared_ptr konstruiert wird?



  • Also so wie ich das verstanden habe, kann es MÖGLICH sein das Funktionsargumente in keiner bestimmten Reihenfolge abgearbeitet werden,und stell dir vor es wird zuerst das 2. Argument abgearbeitet, dort kracht es, dann geht er niemals in das shared_ptr Konstrukt rein.Meine vorstellung der Sache.



  • @Firefighter:

    queer_boy schrieb:

    die begründung passt nicht auf dein beispiel.

    wie pumuckl schon gesagt und hustbaer es wohl gemeint hat, ist es eine sache der angewöhnung. wenn du es bei deiner einparametrigen funktion so machst, wie hustbaer vorschlägt, wirst du es bei allen anderen funktionen auch eher so machen. konsistenz und gewöhnung, das ist alles.

    Genau das.
    Dein Beispiel ist richtig, nur finde ich es besser die Variante vorzuschlagen die auch dann noch funktioniert wenn eine Funktion mehr als nur den shared_ptr als Parameter nimmt. (Deswegen hab ich ja auch "schlecht" und nicht "falsch" geschrieben 😉 )

    Vielleicht wäre es besser gewesen wenn ich gleich erklärt hätte worum es geht 🙂


Anmelden zum Antworten