[C++] Problemy z dynamiczną alokacją tablicy obiektów

Awatar użytkownika
Pneumokok
Użytkownik
Użytkownik
Posty: 48
Rejestracja: 2 sty 2011, o 14:29
Płeć: Mężczyzna
Lokalizacja: Małopolska
Podziękował: 11 razy
Pomógł: 1 raz

[C++] Problemy z dynamiczną alokacją tablicy obiektów

Post autor: Pneumokok »

Witam!
Otóż mam problem z dynamiczną alokacją tablicy obiektów w konstruktorze. Przedstawię kody:

Main.cpp:
Ukryta treść:    
Pociag.h:
Ukryta treść:    
Pociag.cpp:
Ukryta treść:    
Wagon.h:
Ukryta treść:    
Wagon.cpp:
Ukryta treść:    
Debugger narzędzia Netbeans IDE 7.2.1 (kompilator MinGW) twierdzi, że wyciek pamięci następuje w funkcji getLiczbaMiejsc() w pliku Wagon.cpp, a ta funkcja jest wywoływana w funkcji wypiszInfo() w pliku Pociag.cpp. Przy czym.... No jest alokacja pamięci, jest inicjacja liczby miejsc w wagonach dzięki konstruktorowi domniemanemu, a operator new[] zachowuje się tak jakby nie zwracał adresu zaalokowanej dla tablicy pamięci. W obecnej wersji kodu np wskaźnik ma cały czas wartość zero (NULL). Nie mam pojęcia, zdaje mi się że operatora new[] używam właściciwe....

Z góry dziękuję za okazaną pomoc.

Pozdrawiam,
Pneumokok.
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++] Problemy z dynamiczną alokacją tablicy obiektów

Post autor: Afish »

Kod: Zaznacz cały

this->wagony=wagony;
wagony=new Wagon[liczbaWagonow];
Trochę nielogiczny fragment kodu - wagony to argument konstruktora, domyślnie jest nullem, ale może być wskaźnikiem na tablicę wagonów lub wagon bądź jego potomka. Przypisujesz ten argument do pola klasy o tej samej nazwie, a linijkę niżej tworzysz nową tablicę. Co powinieneś zrobić, jeżeli ten argument nie jest nullem? Ponadto zauważ, że tworzysz tablicę i przypisujesz jej adres argumentowi funkcji, więc po zakończeniu konstruktora tej tablicy już nie zwolnisz (bo nie masz wskaźnika). Poprawniej byłoby
this->wagony=new Wagon[liczbaWagonow];
ale ciągle jest to odrobinkę nielogiczne.
Awatar użytkownika
Pneumokok
Użytkownik
Użytkownik
Posty: 48
Rejestracja: 2 sty 2011, o 14:29
Płeć: Mężczyzna
Lokalizacja: Małopolska
Podziękował: 11 razy
Pomógł: 1 raz

[C++] Problemy z dynamiczną alokacją tablicy obiektów

Post autor: Pneumokok »

Ja pierrniczę, wiem już co źle zrobiłem :) Faktycznie - jeśli argument funkcji nazywa się tak samo jak pole klasy istotny jest własnie ten ,,this".
Z przekazaniem wskaźnika, domyślnie NULLa, chodziło mi o to by konstruktor domniemany inicjalizował wszystkie pola klasy z otrzymanej listy argumentów. Czy to konieczne? Szczerze mówiąc nie wiem. Natomiast gdy zmieniłem konstruktor domniemany na:

Kod: Zaznacz cały

Pociag(int liczbaWagonow=5, std::string nazwaPociagu="Wacek");

Kod: Zaznacz cały

Pociag::Pociag(int liczbaWagonow, std::string nazwaPociagu){
    (...)
}
W pliku main.cpp dostaję błąd: main.cpp:16: undefined reference to `Pociag::Pociag(int, std::string, Wagon*)'.
Czyli tak jakby faktycznie standard wymagał, bym w konstruktorze domniemanym inicjalizował każde z pól klasy ,,z zewnątrz", czyli z argumentów które dostaje konstruktor. Natomiast w Symfonii Grębosz pisze:
Kostruktorem, który można wywołać bez żadnych argumentów jest na przykład konstruktor ze wszystkimi argumentami domniemanymi
Z czego wnioskuję, że chodzi o argumenty domniemane konstruktora, a nie pola klasy, gdyż konstruktor może 1 argument przyjmować a pól klasy może być wiele.
Dość dziwne to, wychodzi na to że autor tutaj chyba się myli, o ile dobrze odczytuję jego słowa**.
Co powinieneś zrobić, jeżeli ten argument nie jest nullem?
Fakt, zgubię wtedy to co przekazałem :) Dobrym rozwiązaniem jest alokacja tylko wtedy, gdy (!wagony) ?


**
No i chyba jednak nie, dopisuje sobie zmienne w klasie Pociąg i kompilator nie zgłasza błędu o niezdefiniowanej referencji. Tak jakby przy tamtym błędzie zapisał gdzies sobie, że miał konstruktor z 3 argumentami i nie chciał z takowego zrezygnować.
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++] Problemy z dynamiczną alokacją tablicy obiektów

Post autor: Afish »

Pneumokok pisze:Z przekazaniem wskaźnika, domyślnie NULLa, chodziło mi o to by konstruktor domniemany inicjalizował wszystkie pola klasy z otrzymanej listy argumentów. Czy to konieczne?
Nie, nie trzeba tego robić jawnie (niejawnie pola i tak zostaną zainicjalizowane).
Pneumokok pisze:Natomiast gdy zmieniłem konstruktor domniemany na:

Kod: Zaznacz cały

Pociag(int liczbaWagonow=5, std::string nazwaPociagu="Wacek");

Kod: Zaznacz cały

Pociag::Pociag(int liczbaWagonow, std::string nazwaPociagu){
    (...)
}
W pliku main.cpp dostaję błąd: main.cpp:16: undefined reference to `Pociag::Pociag(int, std::string, Wagon*)'.
Błąd najprawdopodobniej wynika z braku rekompilacji pliku Main.cpp. Dla pewności przebuduj cały projekt, gdyż usunięcie jednego argumentu (o ile usunąłeś go zarówno z pliku cpp jak i z pliku h, a wygląda na to, że tak właśnie zrobiłeś) błędu nie powinno spowodować.
Pneumokok pisze:
Co powinieneś zrobić, jeżeli ten argument nie jest nullem?
Fakt, zgubię wtedy to co przekazałem :) Dobrym rozwiązaniem jest alokacja tylko wtedy, gdy (!wagony) ?
Jest to rozwiązanie, ale czy dobre? Kto wtedy powinien być odpowiedzialny za zwolnienie pamięci? No i co wtedy oznaczałby argument liczbaWagonow? Najlepiej nie kombinować, tylko przyjąć jedno rozwiązanie i się go trzymać - albo wywołujący konstruktor tworzy wagony i później je zwalnia, albo pociąg sam tworzy wagony i sam zajmuje się sprzątaniem.
ODPOWIEDZ