Problem z destruktorem i szablonami.

0

Witam ma problem z poniższym kodem.
Wygląda na to, że program po wejściu do przeciążonego operatora >> tworzy pamięc dla wartosc która potem dopisuje do listy, lecz przy wyjściu z operatora >> pamięc przypisana do wartosc jest zwalniana i pogram się wysypuje.
Kod:

 #include <iostream>

using namespace std;

//--------------------------------------------------MACIERZE-----------------------------------
class macierz_class {
private:
    int liczba_kolumn;
    int liczba_wierszy;
    int *wartosci;
	void zeruj_macierz(){
		for (int i=0;i<liczba_wierszy;++i){
            for (int y=0;y<liczba_kolumn;++y) {
                wartosci[i*liczba_kolumn+y]=0;
            }
        }
	}
public:
    macierz_class (){//KONSTRUKTOR DOMYSLNY
        liczba_kolumn=3;
        liczba_wierszy=3;
        wartosci=new int[liczba_kolumn*liczba_wierszy];
        zeruj_macierz();
    }
    macierz_class(int kolumny, int wiersze) {//KONSTRUKTOR Z PARAMETRAMI
        liczba_kolumn=kolumny;
        liczba_wierszy=wiersze;
        wartosci=new int[liczba_kolumn*liczba_wierszy];
        zeruj_macierz();
    }
	macierz_class(macierz_class &macierz) {	//KOPIUJACY
		liczba_kolumn=macierz.liczba_kolumn;
		liczba_wierszy=macierz.liczba_wierszy;
		wartosci=new int[liczba_kolumn*liczba_wierszy];
        zeruj_macierz();
	}
    ~macierz_class() {
        if(wartosci!= NULL) {
            delete [] wartosci;
            wartosci=NULL;
        }
    }
    friend ostream & operator<< (ostream & s, macierz_class &macierz){            //OPERATOR <<
        for (int i=0;i<macierz.liczba_wierszy;++i){
            for (int y=0;y<macierz.liczba_kolumn;++y) {
                s << macierz.wartosci[i*macierz.liczba_kolumn+y] << " ";
            }
            s << endl;
        }
        return s;
    }
    friend istream & operator>> (istream & s, macierz_class &macierz){            //OPERATOR >>
        for (int i=0;i<macierz.liczba_wierszy;++i){
            for (int y=0;y<macierz.liczba_kolumn;++y) {
                s >> macierz.wartosci[i*macierz.liczba_kolumn+y];
            }
        }
        return s;
    }
};

//----------------------------Elementy listy---------------------------------------
template <class T>
class EL {
    public:
        T wartosc;
        class EL<T>* nastepny;
};


//---------------------------------Lista-------------------------------------------
/*
    Wzorzec:
    Klasa do tego wzorca musi posiadać przeciążone następujące operatory:
        operator>> przypisania
        operator<< wypisania
        operator =
        operator * mnozenie
        operator > boolowski operator
*/
template <class T>
class lista{
    private:
        class EL<T>* pierwszy;
        void dodaj_do_listy(T &wartosc){
    //DODAJ DO LISTY
            EL<T> *nowy_element, *wskaznik;
            wskaznik=pierwszy;
            while (pierwszy != NULL && wskaznik->nastepny != NULL) {
                wskaznik=wskaznik->nastepny;
            }
            nowy_element = new EL<T>;
            nowy_element->wartosc=wartosc;
            nowy_element->nastepny=NULL;
            if(pierwszy == NULL) pierwszy=nowy_element;
            else wskaznik->nastepny=nowy_element;
        }
public:
      lista(){                                        //KONSTRUKTOR
            pierwszy=NULL;
      }
      ~lista(){
            while(pierwszy!=NULL){                    //DESTRUKTOR
              EL<T> *tmp;
              tmp=pierwszy;
              pierwszy=pierwszy->nastepny;
              delete tmp;
            }
      }
      friend ostream & operator<< (ostream & s, lista<T> &list) {  //OPERATOR <<
            EL<T> *wsk;
            wsk=list.pierwszy;
            while (wsk != NULL){
                s << wsk->wartosc<< endl;
                wsk=wsk->nastepny;
            }
            return s;
      }
      friend istream & operator>> (istream & s, lista<T> &list) {  // OPERATOR >>
              int liczba_kolumn=0;
              int liczba_wierszy=0;
              s>>liczba_kolumn;
              s>>liczba_wierszy;
              T wartosc(liczba_wierszy,liczba_kolumn);;
              s>>wartosc;
              list.dodaj_do_listy(wartosc);
              return s;
      }
};
//---------------------------------------------main()-------------------------------------
int main(){
    lista<macierz_class> a,b,c,d;
    cin>>a;
	cout << a;
	cin >> a; //TYLKO DLA ZATRZYMANIA PROGRAMU
    return 0;
}

Bardzo proszę o pomoc, myślę nad tym od kilku dni i nic niewidzę, prawdopodobnie jest to bardzo prosty błąd ale niemogę go zobaczyć.

0

Postaw breakpointa w destruktorze macierz_class(). Teraz jak wejdziesz do metody klasy lista
friend istream & operator>> (istream & s, lista<T> &list)

to zobaczysz, że tworzysz lokalnie obiekt macierz_class:
T wartosc(liczba_wierszy,liczba_kolumn);
dodajesz go do listy:
list.dodaj_do_listy(wartosc);

ktora tworzy płytką kopię "wartosc" i przy wyjściu z metody obiekt "wartosc" jest niszczony (program się zatrzyma w destruktorze macierz_class()). Więc teraz lista zawiera jakieś śmieci. Mi program się nie wywala, tylko "cout << a;" wyświetla jakieś śmieciowe dane.

0

Dzięki, za wskazanie problemu. Czy jest jakiś prosty sposób w jaki mogę to naprawić?

0
macierz_class(macierz_class &macierz) 
{
	liczba_kolumn = macierz.liczba_kolumn;
	liczba_wierszy = macierz.liczba_wierszy;
	wartosci = new int[liczba_kolumn * liczba_wierszy];
	zeruj_macierz();
}

Dlaczego ten konstruktor kopiujący nie kopiuje danych z macierz?

0

Bo w dodaj_do_listy() używasz przypisania:
nowy_element->wartosc=wartosc;

więc potrzebujesz przeciążyć operator =

macierz_class& operator=(const macierz_class& macierz)
{
if(wartosci!= NULL)
{
delete [] wartosci;
wartosci=NULL;
}

liczba_kolumn = macierz.liczba_kolumn;
liczba_wierszy = macierz.liczba_wierszy;
wartosci=new int[liczba_kolumn*liczba_wierszy];
memcpy(wartosci, macierz.wartosci, liczba_kolumn * liczba_wierszy * sizeof(int));

return *this;

}

0
if(wartosci!= NULL)
{
      delete [] wartosci;
      wartosci=NULL;
}
...
wartosci=new int[liczba_kolumn*liczba_wierszy];

Nie ma potrzeby tworzenia aż takiej konstrukcji, wystarczy dać tak:

delete [] wartosci;
...
wartosci = new int[liczba_kolumn * liczba_wierszy];

delete dla wartości NULL nic nie robi.

1 użytkowników online, w tym zalogowanych: 0, gości: 1