Smart Poiner class Frage



  • Ich bin gerade im kapitel 13.5 vom C++ Primer (Lehrbuch) und lese mir gerade einen Zuweisungsoperator durch, der die Verwendung einer Smart-Pointer-Class berücksichtigt, allerdings verstehe ich die Logik bei einer Anweisung überhaupt nicht:

    HasPtr& HasPtr::operator=(const HasPtr &rhs)
    {
      ++rhs.ptr->use;
      if(--ptr->use == 0) delete ptr;  //was soll diese Abfrage? Schritt 1 schließt doch hier das true aus?
      ptr = rhs.ptr;
      val = rhs.val;
      return *this:
    }
    

    hier noch die dazu gehörenden Klassen:

    class HasPtr
    {
      public:
      HasPtr(int* p, int i): ptr(new U_Ptr(o)), val(i) {}
      HasPtr(const HasPtr &orig): ptr(orig.ptr), val(orig.val) {++ptr->use;}
      HasPtr& operator=(const HasPtr&);
      ~HasPtr() { if (--ptr->use == 0) delete ptr;}
      pirvate:
      U_ptr *ptr;
      int val;
    };
    
    class U_Ptr
    {
      friend class HasPtr;
      int *p;
      size_z use;
      U_Ptr(int *p): ip(p), use(1) {};
      ~U_Ptr() {}
    };
    

    wär schön wenn mir das jemand erklären könnte, bzw n besipiel geben könnte wo diese Bedingung true ergibt und der ptr gelöscht würde.

    lg S.



  • nein
    schritt 1 erhöht den counter für RHS
    schritt 2 vermindert den couter für LHS(this)

    das das so rum geschrieben ist, hat den grund, dass sonst selbstzuweisung nicht funktionieren würde...
    (andersrum wär es vrmtl intuitiver)

    bb



  • Bin mir nicht sicher ob ich dich verstanden habe.
    Könntest du/jemand mir vll schritt für schritt aufschreiben was bei obj = obj bei diesem Zuweisungsoberator passiert? Vll versteh ich es dann.



  • // Bezieht sich auf den rechten Operanden der Zuweisung
    ++rhs.ptr->use;
    
    // Bezieht sich auf this.ptr
    if(--ptr->use == 0) delete ptr;
    

    Bei einer Selbstzuweisung wird zuerst rhs.ptr inkrementiert. rhs.ptr entspricht hierbei aber this.ptr (oder einfach ptr). In der folgenden if-Abfrage wird ptr dektrementiert, sodass am Ende gar nichts passiert ist.

    bnz


  • Administrator

    Beispiel einer normalen Zuweisung:

    A = B;
    
                             Counter A                 Counter B
    Start                       1                         3
    ++rhs.ptr->use;             1                         4
    if(--ptr->use == 0)         0                         4
     -> delete von ptr in A.
    ptr = rhs.ptr;              4                         4
    

    Selbstzuweisung:

    A = A;
    
                             Counter A                 Counter A
    Start                       1                         1
    ++rhs.ptr->use;             2                         2
    if(--ptr->use == 0)         1                         1
     -> Kein delete.
    ptr = rhs.ptr;              1                         1
    

    Wenn bei der Selbstzuweisung zuerst die Überprüfung kommen würde:

    A = A;
    
                             Counter A                 Counter A
    Start                       1                         1
    if(--ptr->use == 0)         0                         0
     -> delete von ptr in A.
    ++rhs.ptr->use;             CRASH; BUMM; PATAMM; BENG
    

    Grüssli 😉



  • danke, jetzt versteh ich. Ich hatte garnicht bedacht das die zuweisung erst nach der überprüfung ist. Jetzt macht das ganze sinn. Danke.


  • Administrator

    Jud4s schrieb:

    jo, zu dem Schluss bin ich auch gekommen^^, nur ich habe mich gefragt wieso zwei sinnloszeilen schreiben? Da muss doch ein tieferer Sinn liegen.

    Sinnlos? Wieso sollen die sinnlos sein? Die beziehen sind auf unterschiedliche Objekte!

    Grüssli



  • war auf den vorposter bezogen

    noch ne Frage zum Thema:

    dieser ganze Code wurde ja geschrieben damit das kein crash ergibt:

    int* ip = new int(42);
    
    HasPtr ptr(ip,10);
    
    delete ip;
    
    ptr.set_ptr_val(0);
    

    aber das problem besteht doch immernoch?
    Wenn der Benutzer es lustig findet ip zu deleten wird doch auch der new int gelöscht oder? Oder ist das hier so wie bei Java das solange eine Referenz (in dem Falle Pointer) auf das Objekt verweist lebt es?



  • man benutzt so nen teil ja auch so:

    HasPtr foo(new int(42));
    
    foo.set_val(14);
    

    bb



  • ok, danke ihr habt mir sehr geholfen :D.
    habt ihr auch mit diesem Buch gelern?



  • ich nicht - aber der c++ primer hat auf jeden fall nen sehr guten ruf 😉


Anmelden zum Antworten