2011-06-28 11 views
8

Mam następujący kod i zastanawiam się, czy konieczne jest tutaj delete b? Czy mój system operacyjny automatycznie usunie przydzielony obszar pamięci?Czy konieczne jest usunięcie w destruktorze?

class A 
{ 
    B *b; 

    A() 
    { 
     b = new B(); 
    } 

    ~A() 
    { 
     delete b; 
    } 
}; 

Wielkie dzięki.

+5

["A" również potrzebuje konstruktora kopiowania i operatora przypisania] (http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three). – GManNickG

Odpowiedz

10

Tak, trzeba delete każdy obiekt stworzony z newże jesteś właścicielem. W tym przypadku wygląda na to, że class A jest właścicielem tego samego wystąpienia class B i odpowiada za wywołanie delete.

Będziesz znacznie lepiej wykorzystywać inteligentny wskaźnik do zarządzania czasem życia instancji class B. Zauważ też, że musisz zaimplementować lub zabronić operatorowi przypisania i konstruktorowi kopiowania w class A, aby zapobiec płytkiemu kopiowaniu obiektu, który spowoduje wiele problemów.

1

Z pewnością jest to konieczne, jak to napisałeś. Jednak nawet w przypadku klasy delete klasa jest zasadniczo uszkodzona, ponieważ zarządza zasobem, ale nie jest zgodna z the rule of three.

Powiedział, że prawie na pewno nie ma powodu do ręcznego zarządzania pamięcią - rzadko jest. Jest wielce prawdopodobne, że należy albo po prostu mieć B obiekt jako zmiennej składowej, lub należy używać inteligentne wskaźnik, jak QScopedPointer:

struct A 
{ 
    QScopedPointer<B> b; 
    A() : b(new B()) { } 

    // No ~A() needed; when the A object is destroyed, QScopedPointer ensures 
    // that the B object pointed to by the member 'b' is destroyed and deleted. 
}; 

Będziemy chcieli, aby upewnić się, że masz a good introductory C++ book tak, że można naucz się pisać prawidłowe programy w C++.

5

Prawdopodobnie Twój system operacyjny zwolni przydzieloną pamięć - ale dzieje się tak, gdy twój program się zakończy. Długotrwałe programy będą uruchamiać problemy z pamięcią.

Zawsze dobrze jest używać inteligentnych wskaźników do dynamicznie pokrytych obiektów. Będą robić wszystkie rzeczy do usunięcia dla ciebie.

  • std :: auto_ptr
  • boost :: shared_ptr
  • boost :: scoped_ptr
1

Będzie to wyczyścić powierzchnię tylko wtedy, gdy kończy się proces, ale obszar pozostanie przydzielone przez cały czas do tego czasu, co oznacza memory leak.

2

Jeśli wywołasz nowe, odpowiednie usunięcie jest zawsze zalecane.

Jeśli chodzi o system operacyjny usuwający pamięć ... tak, stanie się tak, ale dopiero po zakończeniu całego procesu (tzn. Twoja aplikacja zostanie zamknięta). Tylko wtedy cała pamięć i inne zasoby są odzyskiwane przez system operacyjny.

Po trzecie, spróbuj użyć nowego/usunąć tylko wtedy, gdy jest to konieczne. W twoim scenariuszu możesz po prostu napisać

class A 
{ 

B b; 

    A() {} 

    ~A() {} 

}; 

Byłby to ten sam efekt i unikniesz dodatkowej dynamicznej alokacji pamięci.

0

Członek b zostanie przydzielony na stercie. Prawdą jest, że system operacyjny zwolni całą pamięć zajmowaną przez stertę; jednak stanie się to tylko raz: na wyjściu programu.

Więc jeśli nie zwolnisz przydzielonych bloków sterty w momencie, gdy staną się nieużywane (zazwyczaj w destruktorze jakiegoś obiektu), ryzykujesz uzyskanie memory leak.

Więc odpowiedź jest w zasadzie: tak, trzeba zadzwonić delete ręcznie, a pamięć nie zostanie zwolniona ASAP automagicznie (choć inteligentne wskazówki pomogą Ci osiągnąć coś podobnego).

0

Wszystko, co przydzielisz z new powinieneś zwolnić za pomocą delete, w przeciwnym razie wystąpi przeciek pamięci w twojej aplikacji.

W przypadku większości nowoczesnych systemów operacyjnych (z pewnością systemów operacyjnych uruchamianych zwykle na komputerach stacjonarnych) wszystko, czego proces używa, zostanie oczyszczone po zakończeniu procesu, więc w przypadku zapomnienia o numerze delete pamięć zostanie zwolniona. Ale powinieneś polegać na tym.

Dawno temu programowałem na Amiga w C. Jego system operacyjny był znacznie mniej wyrafinowany niż dzisiejsze systemy operacyjne. Jeśli przydzielisz pamięć i jej nie zwolnisz, pozostanie ona przydzielona do czasu wyłączenia lub ponownego uruchomienia komputera, nawet po zakończeniu procesu. Przecieki pamięci były wtedy jeszcze poważniejszym problemem.

1

Zarządzanie zasobami to coś więcej niż tylko zwalnianie pamięci. Tak, na większości platformach każda pamięć zostanie przydzielona po zakończeniu procesu, a pamięć jest na tyle tania, że ​​być może nie zauważysz jej przez jakiś czas. Ale co powiesz na plik b, czy muteks odblokuje w swoim destruktorze? Cóż, zanim zabraknie Ci pamięci, możesz napotkać problemy z wynajmowania swoich obiektów poza ich użytecznością.

0

1) Długotrwałe aplikacje napotkają problemy, ponieważ system operacyjny może odzyskać pamięć tylko wtedy, gdy aplikacja przestaje działać.

2) delete b; powoduje również uruchomienie destruktora wskazanej instancji B. W przeciwnym razie nigdy nie będzie działać, ponieważ nie ma już sposobu, aby się do niego dostać. Ten destruktor może zrobić coś ważnego.

Powiązane problemy