Dodanie destruktora powoduje, że program się wysypuje
Ostatnio zmodyfikowano 2017-02-08 19:39
glikoo Temat założony przez niniejszego użytkownika |
Dodanie destruktora powoduje, że program się wysypuje » 2017-02-07 18:26:20 Witam Mam problem z poniższym kodem. Kod się kompiluje i uruchamia dopóki nie zostanie odkomentowana część z destruktorem. Nie mogę zrozumieć co jest przyczyną. Odkomentowanie destruktora sprawia, ze program dalej się kompiluje, ale od razu po uruchomieniu wyskakuje błąd. #include <iostream>
using namespace std;
class kuku { string * tab; public: kuku() : tab( new string[ 2 ] ) { tab[ 0 ] = "none"; tab[ 1 ] = "none2"; } kuku( const string & a, const string b ) : tab( new string[ 2 ] ) { tab[ 0 ] = a; tab[ 1 ] = b; } kuku( const kuku & obj ) : tab( new string[ 2 ] ) { tab[ 0 ] = obj.tab[ 0 ]; tab[ 1 ] = obj.tab[ 1 ]; } const string & operator []( int i ) const { if( i > 1 ) { i = 1; } return tab[ i ]; } string & operator []( int i ) { if( i > 1 ) { i = 1; } return tab[ i ]; } };
ostream & operator <<( ostream & wyjsc, const kuku & obj ) { wyjsc << "Imie perwszej osoby: " << obj[ 0 ] << ", imie drugiej osoby: " << obj[ 1 ] << endl; return wyjsc; }
int main() { cout << "Hello world!" << endl; kuku o1, o2; const kuku * wsk1 = new kuku( "Ala", "Ola" ); const kuku o3( * wsk1 ); delete wsk1; wsk1 = 0; wsk1 = new kuku( o3 ); o2 = * wsk1; cout << o1 << endl; cout << o2 << endl; cout << "*************" << endl; delete wsk1; wsk1 = 0; o1 = kuku( "Ewa", "Iza" ); cout << o1[ 0 ] << ", " << o1[ 1 ] << endl; o1[ 1 ] = "Jan"; cout << o1[ 0 ] << ", " << o1[ 1 ] << endl; cout << "*************" << endl; cout << o1[ 2 ] << endl; return 0; }
|
|
latajacaryba |
» 2017-02-07 18:58:49 o1 = kuku( "Ewa", "Iza" );
Oto ten rodzynek ;p Napisz operator przypisania. Operator przypisania to nie konstruktor kopiujący. Nie wgłębiałem się w kod, ale stawiam, że wskaźnik string o1 wskazuje na jakiegoś stringa w obiekcie kuku. Tablica dynamicznie zaalokowana w kuku jest usuwana destruktorem. Następnie to samo ma się stać z o1, ale tam nie ma czego usuwać (brak tablicy, którą usunąłby destruktor) Napisz więc operator przypisania i odpisz, czy coś to dało ;) |
|
Mister123450 |
» 2017-02-07 19:21:39 Błąd powoduje const kuku * wsk1 = new kuku("Ala", "Ola"); W ten sposób tworzysz wskaźnik na wartość stałą, której nie można usunąć. Na http://kondel.dx.am/?pid=24 masz to wystarczająco opisane, ewentualnie odsyłam do Megatutorialu xiona http://xion.org.pl/files/texts/mgt/html/1_8.html |
|
michal11 |
» 2017-02-07 20:16:45 Tak jak napisał @latajacaryba nie zdefiniowałeś operatora przypisania więc został on wygenerowany automatycznie i nie byłby to problem gdyby nie to, że w twojej klasie jest wskaźnik na dynamicznie alokowaną pamięć więc automatycznie wygenerowany operator przypisania wykonuje tzw. płytkie kopiowanie czyli kopiuje tylko adresy, po takiej operacji będziesz miał dwa obiekty które wskazują na to samo miejsce w pamięci więc kiedy pierwszy zostanie usunięty poprawnie zwolni pamięć ale już kiedy zostanie wywołany konstruktor drugiego obiektu dostaniesz błąd bo będziesz chciał zwalniać już zwolnioną pamięć. Rozwiązaniem jest wspomniane napisanie swojego operatora przypisania. @latajacaryba Mała korekta tylko Operator przypisania to nie konstruktor kopiujący |
oczywiście masz rację z tym, że taki kod Type obj = otherObj wywoła konstruktor kopiujący a nie jak by się mogło wydawać operator przypisania. @Mister123450 nie wiem skąd wziąłeś tą informację, że const pointera nie można usuwać deletem ale to nie jest prawda. Bo w zasadzie dlaczego nie można by było takiego obiektu usunąć? Na poparcie moich słów: http://stackoverflow.com/questions/755196/deleting-a-pointer-to-const-t-consthttp://stackoverflow.com/questions/6965796/why-delete-can-perform-on-pointers-to-const-while-free-cannothttp://stackoverflow.com/questions/756109/how-does-delete-deal-with-pointer-constness |
|
latajacaryba |
» 2017-02-07 21:00:11 @Up Tak, konstruktor kopiujący jest wywoływany w przypadku Ale nie w przypadku Tak dla autora, żeby wiedział :D A co do programu: Jeśli nie zdefiniujesz operatora =, to zostanie on automatycznie wygenerowany na zasadzie "składnik = składnik z przypisywanego obiektu" class A { int a; const int b; double * ptr; A( int aa, int bb, double p ) : ptr( new double( p ) ) { a = a; b = bb; } };
int main() { class A obj1( 1, 2, 5.5 ), obj2( 2, 3, 0.2 ); obj1 = obj2; }
Jeśli nie zdefiniujesz operatora = to wyjdzie to tak: obj1.a = obj2.a obj1.b = obj2.b obj1.ptr = obj2.ptr
Jasne, czy coś niedokładnie lub źle wytłumaczyłem? |
|
glikoo Temat założony przez niniejszego użytkownika |
» 2017-02-08 19:39:56 @latajacaryba Tak, wszystko jasne i program już działa. Dzięki za obrazowe wytłumaczennie :) |
|
« 1 » |