Wieso ist Klasse NICHT exception safe?



  • template <class T>
    class Stack
    {
       private:
          // list node
          struct Node
          {
             T data;
             Node* next;
          };
    
          // recursive list copy
          Node* copy(Node* orig)
          {
             Node* cp = 0;
             if(orig)
             {
                cp = new Node(*orig);
                cp->next = copy(orig->next);
             }
             return cp;
          }
    
          // head of the list
          Node* head;
    
       public:
          Stack() : head(0) {}
          Stack(const Stack & other) : head(copy(other.head)) {}
          ~Stack() { while (!empty()) pop(); }
    
          Stack & operator=(const Stack & rhs)
          {
             while (!empty()) pop();
             head = copy(rhs.head);
             return *this;
          }
    
          bool empty() const { return head == 0; }
    
          void push(const T & t)
          {
              Node* newnode = new Node;
              newnode->next = head;
              head = newnode;
              head->data = t;
          }
    
          T pop()
          {
             if (empty()) throw "pop() in empty stack";
             Node* tmp = head;
             head = head->next;
             T value = tmp->data;
             delete tmp;
             return value;
          }
    };
    

    Bin für jeden Hint dankbar!



  • Meine Vermutung: Du hast den op= und den Copy-CTor von T nicht berücksichtigt. Wenn in push die Zuweisung an head->data eine Exception verursacht, hast du ein leeres Element in deinem Stack. Noch schlimmer: Wenn die Zuweisung an value oder die Kopie von T am Ende von pop eine Exception verursacht, dann kommst du an das Element nie wieder ran.



  • template <class T>
    class Stack
    {
       private:
          // list node
          struct Node
          {
             T data;
             Node* next;
          };
          // recursive list copy
          Node* copy(Node* orig)
          {
             Node* cp = 0;
             if(orig)
             {
                cp = new Node(*orig); //was wenn diese zuweisung ne exception wirft?
                cp->next = copy(orig->next);
             }
             return cp;
          }
          // head of the list
          Node* head;
       public:
          Stack() : head(0) {}
          Stack(const Stack & other) : head(copy(other.head)) {}
          ~Stack() { while (!empty()) pop(); }
          Stack & operator=(const Stack & rhs)
          {
             while (!empty()) pop();
             head = copy(rhs.head); //was wenn copy ne exception wirft?
             return *this;
          }
          bool empty() const { return head == 0; }
          void push(const T & t)
          {
              Node* newnode = new Node;
              newnode->next = head;
              head = newnode;
              head->data = t; //was wenn diese zeile ne exception wirft
          }
          T pop()
          {
             if (empty()) throw "pop() in empty stack";
             Node* tmp = head;
             head = head->next;
             T value = tmp->data; //was wenn diese zeile ne exception wirft?
             delete tmp;
             return value; //was wenn diese zeile eine exception wirft?
          }
    };
    

    lies dir mal Exceptional C++ durch, da wird ein exceptionsicherer Stack entworfen. Dieser Stack sollte auch in den GotW-Artikeln drinnen sein.

    pop() kann nie exception sicher sein, wenn es einen wert liefert. Mach daraus ein pop() und ein top() wobei pop() void liefert und top() das oberste element.

    implementiere copy nicht so, sondern implementiere den op= durch den CCtor ->

    Stack const& operator=(Stack other)
    {
      Swap(other); //zu implementieren: vertauscht nur die member, hat nothrow garantie, kopiert nix
      return *this;
    }
    

    und schon ist der code kuerzer 🙂
    nun musst du noch den CCtor implementieren - dafuer eignet sich deine copy implementierung nur minimal - mach diese auch exception sicher.

    [ Dieser Beitrag wurde am 26.06.2003 um 09:44 Uhr von Shade Of Mine editiert. ]



  • danke


Anmelden zum Antworten