Question

j'ai un class A qui utilise une allocation de mémoire tas pour l'un de ses champs.La classe A est instanciée et stockée sous forme de champ de pointeur dans une autre classe (class B.

Quand j'en ai fini avec un objet de classe B, j'appelle delete, que je suppose appelle le destructeur...Mais cela appelle-t-il également le destructeur de classe A ?

Modifier:

D'après les réponses, je déduis que (veuillez modifier si incorrect) :

  1. delete d'une instance de B appelle B::~B();
  2. qui appelle A::~A();
  3. A::~A devrait explicitement delete toutes les variables membres allouées au tas de l'objet A ;
  4. Enfin, le bloc mémoire stockant ladite instance de classe B est renvoyé au tas - lorsque nouveau a été utilisé, il a d'abord alloué un bloc de mémoire sur le tas, puis a invoqué des constructeurs pour l'initialiser, maintenant, après que tous les destructeurs ont été invoqués pour finaliser l'objet, le bloc où résidait l'objet est renvoyé dans le tas.
Était-ce utile?

La solution

Le destructor A sera exécutée lorsque sa durée de vie est terminée. Si vous voulez la mémoire à libérer et la course de destructor, vous devez le supprimer si elle a été alloué sur le tas. Si elle a été allouée sur la pile cela se produit automatiquement (à savoir quand il est hors de portée, voir RAII). Si elle est membre d'une classe (pas un pointeur, mais un membre à part entière), cela se produira lorsque l'objet contenant est détruit.

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

Dans l'exemple ci-dessus, tous les supprimer et supprimer [] est nécessaire. Et pas de suppression est nécessaire (ou même en mesure d'être utilisé) où je ne l'utilise pas.

auto_ptr, et unique_ptr etc ... sont shared_ptr super pour faire beaucoup plus facile cette gestion à vie:

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

Autres conseils

Lorsque vous appelez supprimer sur un pointeur alloué par la nouvelle, le destructeur de l'objet pointé sera appelé.

A * p = new A;

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

Il est nommé "destructor", pas "deconstructor".

A l'intérieur du destructor de chaque classe, vous devez supprimer toutes les autres variables membres qui ont été attribués à nouveau.

edit: Pour clarifier:

Disons que vous avez

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

Allouer une instance de B, puis la suppression est propre, parce que ce B sera également à l'attribution d'être supprimés dans le destructor.

Mais les instances de la classe C fuiront mémoire, car elle attribue une instance de laquelle il ne libère pas (dans ce cas, C n'a même pas un destructor).

Si vous avez un pointeur habituelle (A*), le destructor ne sera pas appelé (et la mémoire pour exemple ne sera pas A être libéré soit) à moins que vous ne explicitement dans destructor delete de B. Si vous voulez regarder la destruction automatique à des pointeurs intelligents comme auto_ptr.

Vous devez supprimer vous-même dans le destructor 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;
    }
};

Quand tu fais :

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

Le destructeur ne sera appelé que si votre classe de base possède le mot-clé virtual.

Ensuite, si vous n'aviez pas de destructeur virtuel, seul ~B() serait appelé.Mais puisque vous avez un destructeur virtuel, ~D() sera d'abord appelé, puis ~B().

Aucun membre de B ou D alloué sur le tas ne sera libéré à moins que vous ne les supprimiez explicitement.Et les supprimer appellera également leur destructeur.

Je me demandais pourquoi ma classe destructor n'a pas été appelé. La raison était que j'avais oublié d'inclure la définition de cette catégorie (#include « class.h »). Je n'avais une déclaration comme « classe A »; et le compilateur était heureux avec elle et me laisser appeler « supprimer ».

Non. le pointeur sera supprimé. Vous devez appeler la supprimer sur un explicite dans le destructor B.

Le destructor pour l'objet de la classe A ne sera appelée que si suppression est appelée pour cet objet. Assurez-vous de supprimer ce pointeur dans la destructor de la classe B.

Pour un peu plus d'informations sur ce qui se passe quand la suppression est appelée sur un objet, voir: http://www.parashift.com/c++- faq-lite / Freestore-mgmt.html # faq-16.9

Non, ce ne sera pas appeler destructor pour une classe, vous devez appeler explicitement (comme PoweRoy dit), supprimer la ligne « supprimer ptr; » dans l'exemple de comparer ...

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

Vous avez quelque chose comme

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

Si vous appelez ensuite delete b;, rien ne se passe à un, et vous avez une fuite de mémoire. Essayer de se rappeler de n'est pas une delete b->a; bonne solution, mais il y a deux ou trois autres.

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

Ceci est un destructor B qui va supprimer un. (Si un est 0, qui ne fait rien supprimer. Si un est différent de 0, mais ne pointe pas à la mémoire de nouveau, vous obtenez la corruption du tas.)

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

De cette façon, vous n'avez pas comme un pointeur, mais plutôt un auto_ptr <> (shared_ptr <> va faire aussi bien, ou d'autres pointeurs intelligents), et il est automatiquement supprimé lorsque b est.

Chacune de ces façons fonctionne bien, et je l'ai utilisé à la fois.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top