Ist das hier falsche Benutzung eines shared_ptr?



  • EOutOfResources schrieb:

    Shade Of Mine schrieb:

    Dann erklaer mal deine Aussage bzgl Stack/Heap.

    Ich verstehe nicht, was es daran auszusetzen gibt, dass ich das Objekt auf dem Stack statt über einen Smartpointer auf dem Heap anlege.

    Weil es beim Verlassen des Scopes zerstört wird und man halt 'manchmal' Objekte hat, die länger leben sollen...

    EDIT: Ich hoffe er verwendet hier nur Smart-Pointer wegen Code-Reduktion... Zumal er noch threadsafe ist 🙄



  • EOutOfResources schrieb:

    Shade Of Mine schrieb:

    Dann erklaer mal deine Aussage bzgl Stack/Heap.

    Ich verstehe nicht, was es daran auszusetzen gibt, dass ich das Objekt auf dem Stack statt über einen Smartpointer auf dem Heap anlege.

    Und Nachts ist es kaelter als draussen.

    Wenn du etwas auf den Stack anlegen kannst - dann bedeutet dies, dass du die Lebenszeit des Objektes nicht dynamisch festlegst sondern statisch. Es bedeutet, dass dieses Objekt eine genau definierte, statische, Lebensdauer hat.

    Hier verwendet man nie Smartpointer. Es wuerde keinen Sinn machen.

    Wenn aber die Lebensdauer dynamisch sein muss, dann muss man das Objekt per new oder aehnlichem anlegen und genau dann sind Smartpointer erstmal erste Wahl.

    Und genau das verwirrt hier. Denn Stack Objekte mit Smartpointern vergleichen ist dumm. Das deutet daraufhin dass du etwas grundlegendes nicht verstanden hast. Deshalb die Frage ob du es erklaeren kannst.

    PS:
    einzeilige Posts zeigen auch nicht wirklich von viel interesse etwas sinnvolles zu dieser diskussion beizutragen...



  • Shade Of Mine schrieb:

    Es bedeutet, dass dieses Objekt eine genau definierte, statische automatische, Lebensdauer hat.

    Ich hätte nicht gemeckert, wenn da ein anderes Wort als statisch stehen würde, aber statische Lebensdauer ist etwas anderes (auch wenn ich annehme, dass du das weisst). 😉



  • drakon schrieb:

    Shade Of Mine schrieb:

    Es bedeutet, dass dieses Objekt eine genau definierte, statische automatische, Lebensdauer hat.

    Ich hätte nicht gemeckert, wenn da ein anderes Wort als statisch stehen würde, aber statische Lebensdauer ist etwas anderes (auch wenn ich annehme, dass du das weisst). 😉

    Statisch im Sinne von Starr (gegenteil von dynamisch). Nicht static.



  • EOutOfResources schrieb:

    Shade Of Mine schrieb:

    Dann erklaer mal deine Aussage bzgl Stack/Heap.

    Ich verstehe nicht, was es daran auszusetzen gibt, dass ich das Objekt auf dem Stack statt über einen Smartpointer auf dem Heap anlege.

    Das eine hat doch nichts mit dem anderen zu tun.
    Wie willst du denn einen dynamischen Baum mit Knoten aufbauen, wenn du nur den Stack benutzt? So ein Schwachsinn



  • Omgg schrieb:

    Wie willst du denn einen dynamischen Baum mit Knoten aufbauen, wenn du nur den Stack benutzt? So ein Schwachsinn

    Wenn man die Klasse selbst schreibt, kann man die Allokation und die Freigabe selbst übernehmen...



  • EOutOfResources schrieb:

    Wenn man die Klasse selbst schreibt, kann man die Allokation und die Freigabe selbst übernehmen...

    Ich dachte, du würdest was von RAII halten 😉

    Sieh es doch ein, Smart-Pointer sind äusserst sinnvoll. Erst recht sobald der Code etwas komplexer wird und mehrere return -Statements oder Exceptions vorkommen können. Stack-Objekte helfen dir auch nicht immer weiter, in solchen Fällen wird der Code ohne Smart-Pointer extrem umständlich.



  • EOutOfResources schrieb:

    Omgg schrieb:

    Wie willst du denn einen dynamischen Baum mit Knoten aufbauen, wenn du nur den Stack benutzt? So ein Schwachsinn

    Wenn man die Klasse selbst schreibt, kann man die Allokation und die Freigabe selbst übernehmen...

    Dennoch kann die Allokation nicht auf dem Stack stattfinden.

    PS:
    Oder zeig eine implementierung einer add() methode fuer eine beliebige Datenstruktur die ohne dynamische Allokation auskommt.



  • EOutOfResources, im folgenden ein kurzes Beispiel (hier sogar nur mit lokaler Variablengültigkeit).

    Deine Aufgabe besteht darin, ohne Smart-Pointer äquivalenten Code zu schreiben. Gehe davon aus, dass jede aufgerufene Funktion der Klassen Base , Derived1 und Derived2 eine Exception werfen kann.

    int Fn()
    {
        scoped_ptr<Derived1> a(new Derived1);
        scoped_ptr<Base> b;
        if (...)
            b.reset(new Derived1);
        else
            b.reset(new Derived2);
    
        if (b->MemFn1())
            return 2;
    
        a->MemFn2();
        if (b->MemFn3())
            return 4;
        else
            return 7;
    }
    


  • Im Grunde weiß EOutOfResources ja selber, dass seine Haltung Quatsch ist und ein Indiz für Unerfahrenheit ist. Nur aufgrund falschen Stolzes kann er halt jetzt nicht seinen Fehler eingestehen...



  • @nexus:

    das ist möglich, ich hab sogar in etwa was vor meinem geistigen auge, aber da kommt redundanter code dazu, und jede einzelne exception wird einzeln per try abgefangen...



  • Nexus schrieb:

    EOutOfResources, im folgenden ein kurzes Beispiel (hier sogar nur mit lokaler Variablengültigkeit).

    Deine Aufgabe besteht darin, ohne Smart-Pointer äquivalenten Code zu schreiben. Gehe davon aus, dass jede aufgerufene Funktion der Klassen Base , Derived1 und Derived2 eine Exception werfen kann.

    int Fn()
    {
        scoped_ptr<Derived1> a(new Derived1);
        scoped_ptr<Base> b;
        if (...)
            b.reset(new Derived1);
        else
            b.reset(new Derived2);
    
        if (b->MemFn1())
            return 2;
    
        a->MemFn2();
        if (b->MemFn3())
            return 4;
        else
            return 7;
    }
    
    int Fn()
    {
        Derived1 a;
        if (...) {
            Derived1 b;
            return helper(a,b);        
        }
        else {
            Derived2 b;
            return helper(a,b);
        }
    }
    
    int helper(Derived1& a, Base& b) {
        if (b.MemFn1())
            return 2;
    
        a.MemFn2();
        if (b.MemFn3())
            return 4;
        else
            return 7;
    }
    


  • Isomorph+ schrieb:

    Im Grunde weiß EOutOfResources ja selber, dass seine Haltung Quatsch ist und ein Indiz für Unerfahrenheit ist. Nur aufgrund falschen Stolzes kann er halt jetzt nicht seinen Fehler eingestehen...

    Jup, das kommt davon wenn man schreibt ohne nachzudenken. 😉



  • Nicht schlecht, life! Was machst du, wenn wir

    if (...)
        b.reset(new Derived1);
    else
        b.reset(new Derived2);
    

    ersetzen durch

    Base* CreateDerived(); // Funktionsdeklaration
    b.reset(CreateDerived());
    

    ? Oder falls wir das Derived -Objekt nach der Funktion noch verwenden wollen? 🙂



  • Oder falls wir leserlichen Code wollen? 🙄



  • Nexus schrieb:

    Nicht schlecht, life! Was machst du, wenn wir

    if (...)
        b.reset(new Derived1);
    else
        b.reset(new Derived2);
    

    ersetzen durch

    Base* CreateDerived(); // Funktionsdeklaration
    b.reset(CreateDerived());
    

    ? Oder falls wir das Derived -Objekt nach der Funktion noch verwenden wollen? 🙂

    Ich verwende Smartpointer. Wobei ich bei deinem Beispiel die Lösung ohne Smartpointer sogar fast eleganter finde..



  • Smartpointer helfen halt, dass die Speicherverwaltung automatisch erledigt wird. Aber ich finde, die sind kein Muss. Die inflationäre Benutzung davon ist in meinen Augen nicht immer nötig. Es gibt aber viele Fälle, in denen die hilfreich sind.



  • Eisflamme schrieb:

    Aber ich finde, die sind kein Muss. Die inflationäre Benutzung davon ist in meinen Augen nicht immer nötig.

    Sehr vorsichtig ausgedrückt 😃

    Normalerweise besteht aber kein Grund, Smart-Pointer nicht zu verwenden. Gerade bei so einer einfachen Sache wie scoped_ptr , wo man sich das delete sparen und sich sicher sein kann, dass der Code auch nach einer Änderung in einem Jahr noch ohne Leaks ist. Was eher ein Problem darstellt, ist der übermässige Einsatz von shared_ptr , obwohl man keinen geteilten Besitz will. Zum Beispiel in STL-Containern. Meist will man statt vector<shared_ptr<T>> einen ptr_vector<T> .



  • Mache ich davon Gebrauch, dass man die Verwaltung einer Ressource einem anderen Objekt überlässt? Ja. Gerne.

    Nutze ich schlaue Zeiger? So gut wie gar nicht. Hat jetzt aber nichts mit Prinzipien zu tun. Ich habe schlaue Zeiger bisher so gut wie gar nicht benötigt. Das hat sicherlich auch was mit meinen Anwendungsbereichen zu tun (Ich bastel zB kaum GUIs).



  • @krümelkacker:
    Ich finde es mit Smart-Pointern halt viel übersichtlicher, weniger fummelig und weniger fehleranfällig wenn man Ownership transferiert.
    Spätestens mit C++0x gibt es IMO kein gutes Argument mehr es nicht zu machen. Denn da haben wir std::unique_ptr , und der ist schlank und movable. Und alles wird gut 🙂


Anmelden zum Antworten