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):

  1. delete przykład B wywołuje B::~B ();
  2. które wywołują A::~A();
  3. and A::~A należy jawnie delete wszystkie zmienne składowe przypisane do sterty a;
  4. 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.
Author: Unihedron, 2009-03-24

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
 164
Author: Eclipse,
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
 27
Author: ,
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:36:11

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).

 22
Author: Sebastian Mach,
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.

 5
Author: sharptooth,
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.

 4
Author: corné,
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.

 2
Author: Brian R. Bondy,
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".

 1
Author: Harri Luoma,
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.

 0
Author: RvdK,
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

 0
Author: Kris Kumler,
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;
  }
 0
Author: Darius Kucinskas,
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.
 0
Author: David Thornley,
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