Frage

Ich habe eine class A, die einen Haufen Speicherzuweisung für einen seiner Felder verwendet. Klasse A wird als Zeigerfeld in einer anderen Klasse (class B instanziiert und gespeichert werden.

Wenn ich mit einem Objekt der Klasse B fertig bin, rufe ich delete, die ich übernehme Anrufe der destructor ... Aber ist dies den destructor der Klasse A nennt auch?

Bearbeiten:

Aus den Antworten, ich nehme die (bitte bearbeiten, wenn falsch):

  1. delete einer Instanz von B ruft B :: ~ B ();
  2. die Anrufe A::~A();
  3. A::~A sollte explizit delete alle Heap zugewiesenen Elementvariablen des A-Objekts;
  4. Schließlich wird der Speicherblock zum Speichern der Instanz der Klasse B auf den Heap zurückgegeben wird - wenn neuen verwendet wurde, ist es zunächst einen Speicherblock auf Heap zugewiesen, dann aufgerufen Konstrukteurs es zu initialisieren, jetzt nach alle Destruktoren aufgerufen wurden das Objekt den Block, in dem das Objekt fertig zu stellen gewohnt wird wieder in den Haufen.
War es hilfreich?

Lösung

Der Destruktor von A wird ausgeführt, wenn ihre Lebensdauer abgelaufen ist. Wenn Sie seinen Speicher wollen befreit werden und die destructor laufen, haben Sie es zu löschen, wenn es auf dem Heap zugewiesen wurde. Wenn es auf dem Stapel reserviert wurde geschieht dies automatisch (das heißt, wenn es außerhalb des Gültigkeitsbereiches geht, siehe RAH). Wenn es ein Mitglied einer Klasse (kein Zeiger, sondern ein vollwertiges Mitglied) ist, dann wird dies geschehen, wenn das enthaltende Objekt zerstört wird.

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

In dem obigen Beispiel jeder löschen und löschen [] benötigt wird. Und kein Löschen erforderlich ist (oder tatsächlich in der Lage verwendet werden), wo ich es nicht verwenden.

auto_ptr, unique_ptr und shared_ptr etc ... sind groß für die Herstellung dieser Lebenszeit-Management viel einfacher:

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

Andere Tipps

Wenn Sie auf einem Zeiger durch neue zugewiesen löschen nennen, der destructor des Objekts aufgerufen wird hingewiesen.

A * p = new A;

delete p;    // A:~A() called for you on obkect pointed to by p

Es heißt "destructor", nicht "Deconstructor".

Im Inneren des destructor jeder Klasse, haben Sie alle anderen Elementvariablen zu löschen, die mit neuen zugeteilt wurden.

edit: Zur Klarstellung:

Angenommen, Sie haben

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;
}

Die Zuweisung eine Instanz von B und dann zu löschen ist sauber, weil das, was B intern zuordnet wird auch in dem destructor gelöscht werden.

Aber Instanzen der Klasse C werden ein Speicherleck, weil es eine Instanz von A zuordnet, die sie nicht freigibt (in diesem Fall C hat noch nicht einmal eine destructor).

Wenn Sie einen gewöhnlichen Zeiger (A*), dann wird der Destruktor nicht aufgerufen werden (und Speicher für A Instanz wird auch nicht befreit werden) wenn Sie nicht ausdrücklich die in delete destructor do B. Wenn Sie die automatische Zerstörung sehen wollen auf intelligente Zeiger wie auto_ptr.

Sie sollten A löschen sich im Destruktor von B.

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;
    }
};

Wenn Sie das tun:

B *pD = new D();
delete pD;

wird der destructor nur, wenn Ihre Basisklasse hat das Schlüsselwort virtual aufgerufen werden.

Dann, wenn Sie keinen virtuellen Destruktor haben nur ~ B () würde genannt werden. Aber da Sie einen virtuellen Destruktor haben, erste ~ D () aufgerufen wird, dann ~ B ().

Es wurden keine Mitglieder von B oder D auf dem Heap zugewiesen werden freigegeben werden, wenn Sie sie explizit löschen. Und sie zu löschen ihre Destruktoraufrufs auch.

Ich habe mich gefragt, warum meine Klasse destructor nicht genannt wurde. Der Grund war, dass ich Definition dieser Klasse (# include „class.h“) schließen vergessen hatte. Ich hatte nur eine Erklärung wie „Klasse A;“ und der Compiler war glücklich mit ihm und lassen Sie rufen Sie mich an „löschen“.

Nein. der Zeiger wird gelöscht. Sie sollten die auf der A explizit im Destruktor von B löschen aufrufen.

Der Destruktor für das Objekt der Klasse A wird nur aufgerufen werden, wenn Lösch für das Objekt aufgerufen wird. Achten Sie darauf, dass die Zeiger in dem destructor der Klasse B zu löschen.

Für eine wenig mehr Informationen darüber, was passiert, wenn löscht auf einem Objekt aufgerufen wird, siehe: http://www.parashift.com/c++- FAQ-lite / Frees-mgmt.html # faq-16.9

Nein, es wird nicht destructor für Klasse A nennen, können Sie es explizit aufrufen sollte (wie PoweRoy gesagt), löschen Zeile ‚löschen ptr;‘ in Beispiel zu vergleichen, ...

  #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;
  }

Sie haben so etwas wie

class B
{
   A * a;
}
B * b = new B;
b->a = new A;

Wenn Sie dann delete b; nennen, geschieht nichts ein, und Sie haben einen Speicherverlust. delete b->a; ist keine gute Lösung zu erinnern, Probieren, aber es gibt ein paar andere.

B::~B() {delete a;}

Dies ist ein Destruktor für B, die eine gelöscht. (Wenn eine 0 ist, das löschen, bringt nichts. Wenn ein nicht 0 ist, aber zeigt nicht von neuen auf den Speicher, erhalten Sie Heapbeschädigung.)

auto_ptr<A> a;
...
b->a.reset(new A);

Auf diese Weise haben Sie nicht ein als Zeiger aber eher ein auto_ptr <> (shared_ptr <> wird auch tun, oder andere intelligente Zeiger), und es wird automatisch gelöscht, wenn b.

Jede dieser Möglichkeiten funktioniert gut, und ich habe beide verwendet.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top