2014-07-18 2 views
0

Я начинаю изучать C++, поэтому решил попробовать реализовать класс, способный хранить числовые значения.
И чтобы добавить немного сложнее, я решил сделать это отсортировано: Элементы стека должны быть отсортированы в порядке возрастания сверху вниз. Я решил использовать NaN для представления пустого стека.C++ реализация класса стека

Так вот файл HPP:

#ifndef MYMSS2_RENAME_ME_HPP 
#define MYMSS2_RENAME_ME_H 
class mySortedStack{ 
    public: 
     double info; 
     mySortedStack * next; 

     mySortedStack(); 
     mySortedStack(double a); 
     mySortedStack(const mySortedStack& a); 
     ~mySortedStack(); 

     double top(); 
     double pop(); 
     void push(double a); 

     int len(); 

}; 
#endif 

и вот файл CPP:

#include <iostream> 
#include "myMSS2_RENAME_ME.hpp" 
#include <math.h> 

using namespace std; 

mySortedStack::mySortedStack(){ 
    //cout<<"Inside empty constuctor"<<endl; 
    info=NAN; 
    next=NULL; 
    //cout<<"Leaving empty constuctor"<<endl; 
} 

mySortedStack::mySortedStack(double a){ 
    //cout<<"Inside normal constructor"<<endl; 
    info=a; 
    next=NULL; 
    //cout<<"Leaving normal constuctor"<<endl; 
} 

mySortedStack::mySortedStack(const mySortedStack& a){//this should be able to do deepcopies 
    //cout<<"Inside copy constructor"<<endl; 
    info=double(a.info); 
    next=new mySortedStack; 
    next=a.next; 
    //cout<<"Leaving copy constuctor"<<endl; 
} 

mySortedStack::~mySortedStack(){ 
    //cout<<"Inside destructor"<<endl; 
    delete this; 
} 

double mySortedStack::top(){ 
    return info; 
} 

void mySortedStack::pop(){ 
    double retVal; 
    mySortedStack *tempStack = this->next; 
    retVal = info; 
    info = tempStack->info; 
    next = tempStack->next; 
    tempStack->next = NULL; 
    delete tempStack; 
    return retVal; 
} 

void mySortedStack::push(double a){ 
    //cout<<"Pushing!"<<endl; 
    if (isnan(info)){//if stack is empty 
     info=a; 
    } 
    else{ 
     mySortedStack *pushed=new mySortedStack(); 
     if(info>a){//if the pushed element will be placed at the top 
      pushed->info=info; 
      pushed->next=next; 
      info=a; 
      next=pushed; 

     }else{//else 
      mySortedStack *currentNode=this; 
      while(currentNode->next->info<a){ 
       currentNode=currentNode->next; 
      } 
      mySortedStack *pushed=new mySortedStack(); 
      pushed->info=a; 
      pushed->next=currentNode->next; 
      currentNode->next=pushed; 
     } 

    } 
} 



int mySortedStack::len(){ 
    int i=1; 
    mySortedStack currentNode=*this; 
    if (isnan(info)){ 
     return 0; 
    } 
    while (currentNode.next!=NULL){ 
     i+=1; 
     currentNode=*currentNode.next; 
    } 
    return i; 
} 

Это компилируется нормально (я использую Dev C++ на Windows 8).

Так что я попытался запустить несколько тестов, добавив main функцию в файле CPP:

int main(){ 
    mySortedStack mss0; 
    mySortedStack mss1(7); 
    mySortedStack mss2=mss1; 
    mss1.info=6; 
    cout<<mss1.info<<' '<<mss2.info<<endl;//copy constructor seems to work! output is '6 7' 

    system("PAUSE"); 

    mss1.push(4); 
    mss1.push(5); 

    //the next piece of code is supposed to show the whole stack 
    bool flag=true; 
    mySortedStack inspected=mss1; 
    while(flag){ 
     cout<<inspected.info<<endl; 
     if(inspected.next==NULL){ 
      flag=false; 
      cout<<"NULL found!"<<endl; 
     } 
     else{ 
      inspected=*inspected.next; 
     } 
    } 
    //seems correct. Output is: 
    //'4 
    //5 
    //6 
    //NULL found!' 
    system("PAUSE"); 
    return 0; 
} 

Aaaannd здесь речь идет! Ошибка сегментации! (Точное сообщение об ошибке: Программный сигнал SIGSEGV, ошибка сегментации) Кажется, что это произошло непосредственно перед return 0.
После добавления некоторого cout<< кажется, что проблема заключается в моем деструкторе (бесконечный цикл). Поскольку я понятия не имею, о каком вызове деструктора это делает, я не имею ни малейшего понятия, связана ли проблема с самим деструктором или с тем, как я манипулирую указателями в методе класса или где-либо еще. Я пытался рисовать на бумаге то, что происходит внутри каждого из моих методов, и все кажется прекрасным.
Что я делаю неправильно?
Благодарим вас заблаговременно.

+0

Не делайте «удалять это» в своем конструкторе. – tomasbasham

+0

@tomasbasahm Деструктор. Но да, не делай этого. –

+0

Да, деструктор. Хороший улов – tomasbasham

ответ

4
mySortedStack::~mySortedStack(){ 
    //cout<<"Inside destructor"<<endl; 
    delete this; // Uuuh ? 
} 

... Я действительно не знаю, что добавить к этому ответу.

Edit: На самом деле, я нашел кое-что:

mySortedStack::mySortedStack(const mySortedStack& a){ 
    // ... 
    next=new mySortedStack; // Hello brand new object ! 
    next=a.next; // Goodbye leaked object ! 
    // ... 
} 
+0

Aha! В дополнение к ответу @StAlphonzo, теперь я понимаю. Я исправил его, заменив 'this' на' next'. Теперь деструктор удаляет каждый элемент стека один за другим. Кроме того, спасибо, что указали на эту ошибку в конструкторе копирования. – TheReader

1

право, но быть конкретными, позвонив по телефону «удалить этот» вы пытаетесь удалить текущий объект, который содержит desctructor. Удалить вызывает дескриптор, который вызывает delete и т. Д., Таким образом, цикл.

Деструктор существует, поэтому вы можете освободить любую память, выделенную вашим классом. Таким образом, когда кто-то вызывает delete mySortedStackInstance (из того, что он вызвал), ваш класс не будет утечки памяти.

Я понял, что должен просто добавить это, чтобы у вас не было больше путаницы в отношении того, что деструктор в вашем классе на самом деле.

0

Сегментация происходит от этой линии

mySortedStack inspected=mss1; 

Вы должны написать правильную копию конструктора.

Есть и другие проблемы памяти в вашем коде:

mySorted стек совершающие самоубийство. Это плохой стиль.

mySortedStack::~mySortedStack(){ 
    //cout<<"Inside destructor"<<endl; 
    delete this; 
} 

Ваш деструктор должен выглядеть следующим образом

mySortedStack::~mySortedStack(){ 
    //cout<<"Inside destructor"<<endl; 
    delete this->mySortedStack; 
} 

Другой недостаток стиля имен: класс и memeber разделяют то же имя. Трудно читать.

Смежные вопросы