Czy delete wywołuje destruktor?
Mam klasę (A), która używa alokacji pamięci sterty dla jednego z jej pól. Klasa A jest tworzona i przechowywana jako pole wskaźnika w innej klasie (B).
Kiedy skończę z obiektem B, wywołuję delete, co zakładam, że wywołuje destruktor... Ale czy to też nazywa Destruktor w klasie A?
Edit:
Z odpowiedzi, biorę to (proszę edytować, jeśli jest niepoprawne):
-
delete
przykład B wywołuje B::~B (); - które wywołują
A::~A();
-
and A::~A
należy jawniedelete
wszystkie zmienne składowe przypisane do sterty a; - i na koniec blok pamięci przechowujący wspomnianą instancję B jest zwracany do sterty - gdy użyto new , najpierw przydzielono blok pamięci na stercie, a następnie wywołano konstruktory, aby go zainicjować, teraz po wywołaniu wszystkich destruktorów, aby sfinalizować obiekt, blok, w którym znajdował się obiekt, jest zwracany do sterty.
11 answers
Destruktor A uruchomi się, gdy jego żywotność dobiegnie końca. Jeśli chcesz, aby jego pamięć została uwolniona i uruchomiony Destruktor, musisz ją usunąć, jeśli została przydzielona na stercie. Jeśli zostało przydzielone na stosie, dzieje się to automatycznie (tzn. gdy wychodzi poza zakres; patrz RAII). Jeśli jest członkiem klasy (nie wskaźnikiem, ale pełnym członkiem), to stanie się tak, gdy zawierający obiekt zostanie zniszczony.
class A
{
char *someHeapMemory;
public:
A() : someHeapMemory(new char[1000]) {}
~A() { delete[] someHeapMemory; }
};
class B
{
A* APtr;
public:
B() : APtr(new A()) {}
~B() { delete APtr; }
};
class C
{
A Amember;
public:
C() : Amember() {}
~C() {} // A is freed / destructed automatically.
};
int main()
{
B* BPtr = new B();
delete BPtr; // Calls ~B() which calls ~A()
C *CPtr = new C();
delete CPtr;
B b;
C c;
} // b and c are freed/destructed automatically
W powyższym przykładzie potrzebne jest każde kasowanie i kasowanie []. I nie delete jest potrzebne (lub rzeczywiście może być używany) tam, gdzie go nie używałem.
auto_ptr
, unique_ptr
i shared_ptr
itd... są świetne do znacznie łatwiejszego zarządzania tym życiem: {]}
class A
{
shared_array<char> someHeapMemory;
public:
A() : someHeapMemory(new char[1000]) {}
~A() { } // someHeapMemory is delete[]d automatically
};
class B
{
shared_ptr<A> APtr;
public:
B() : APtr(new A()) {}
~B() { } // APtr is deleted automatically
};
int main()
{
shared_ptr<B> BPtr = new B();
} // BPtr is deleted automatically
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-14 21:21:24
Gdy wywołasz delete na wskaźniku przydzielonym przez new, zostanie wywołany Destruktor wskazywanego obiektu.
A * p = new A;
delete p; // A:~A() called for you on obkect pointed to by p
Nazywa się "destructor", a nie "deconstructor".
Wewnątrz destruktora każdej klasy, musisz usunąć wszystkie inne zmienne członkowskie, które zostały przydzielone z new.
Edit: do wyjaśnienia:
Powiedz, że masz
struct A {}
class B {
A *a;
public:
B () : a (new A) {}
~B() { delete a; }
};
class C {
A *a;
public:
C () : a (new A) {}
};
int main () {
delete new B;
delete new C;
}
Przydzielanie instancji B, a następnie usuwanie jest czyste, ponieważ to, co B alokuje wewnętrznie, również zostanie usunięte w destruktorze.
Ale instancje klasy C będą wyciekać pamięć, ponieważ przydziela instancję a, której nie release (w tym przypadku C nie posiada nawet destruktora).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-24 14:38:38
Jeśli masz zwykły wskaźnik (A*
), to Destruktor nie zostanie wywołany (a pamięć instancji A
również nie zostanie zwolniona), chyba że wykonasz delete
jawnie w destruktorze B
. Jeśli chcesz automatycznego niszczenia spójrz na inteligentne wskaźniki jak auto_ptr
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-10 15:31:37
Powinieneś usunąć a w destruktorze B.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-24 14:33:55
class B
{
public:
B()
{
p = new int[1024];
}
virtual ~B()
{
cout<<"B destructor"<<endl;
//p will not be deleted EVER unless you do it manually.
}
int *p;
};
class D : public B
{
public:
virtual ~D()
{
cout<<"D destructor"<<endl;
}
};
Kiedy to zrobisz:
B *pD = new D();
delete pD;
Destruktor zostanie wywołany tylko wtedy, gdy twoja klasa bazowa ma słowo kluczowe virtual.
Wtedy, jeśli nie masz Wirtualnego destruktora, wywołane zostanie tylko ~B (). Ale ponieważ masz wirtualny Destruktor, najpierw zostanie wywołane ~D (), a następnie ~B ().
Żaden członek B lub D przydzielony na stercie nie będzie dealokowany, chyba że wyraźnie je usuniesz. A ich usunięcie wywoła również Destruktor.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-24 14:45:53
Zastanawiałem się, dlaczego nie wezwano niszczyciela mojej klasy. Powodem było to, że zapomniałem dodać definicję tej klasy (#include " class.h"). Miałem tylko deklarację typu "class A;" i kompilator był z niej zadowolony i pozwolił mi zadzwonić "delete".
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-17 12:29:43
Nie. wskaźnik zostanie usunięty. Należy wywołać delete na Jawie w destruktorze B.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-24 14:32:13
Destruktor dla obiektu klasy a zostanie wywołany tylko wtedy, gdy dla tego obiektu zostanie wywołane delete. Upewnij się, że usuniesz ten wskaźnik w destruktorze klasy B.
Aby uzyskać więcej informacji o tym, co się dzieje, gdy obiekt zostanie wywołany delete, zobacz: http://www.parashift.com/c++ - faq-lite / freestore-mgmt.html#faq-16.9
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-24 14:35:15
Nie spowoduje wywołania destruktora dla klasy A, powinieneś wywołać go jawnie( tak jak powiedział PoweRoy), usuń linię 'delete ptr;' w przykładzie do porównania ...
#include <iostream>
class A
{
public:
A(){};
~A();
};
A::~A()
{
std::cout << "Destructor of A" << std::endl;
}
class B
{
public:
B(){ptr = new A();};
~B();
private:
A* ptr;
};
B::~B()
{
delete ptr;
std::cout << "Destructor of B" << std::endl;
}
int main()
{
B* b = new B();
delete b;
return 0;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-24 14:50:35
Masz coś takiego
class B
{
A * a;
}
B * b = new B;
b->a = new A;
Jeśli zadzwonisz delete b;
, nic się nie stanie a, i masz wyciek pamięci. Próba zapamiętania delete b->a;
nie jest dobrym rozwiązaniem, ale jest kilka innych.
B::~B() {delete a;}
Jest to destruktor dla B, który usunie a. (jeśli a jest równe 0, to usunięcie nic nie robi. Jeśli a nie jest 0, ale nie wskazuje na pamięć z new, dostajesz korupcję sterty.)
auto_ptr<A> a;
...
b->a.reset(new A);
W ten sposób nie masz jako wskaźnika, ale raczej auto_ptr(shared_ptr zrobi jak również, lub inne inteligentne wskaźniki), i jest automatycznie usuwany, gdy B jest.
Jeden z tych sposobów działa dobrze, a ja użyłem obu.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-24 15:00:40