2 votes

Appeler le destructeur d'un objet dans sa méthode d'opérateur d'affectation

Dans ma méthode d'opérateur d'assignation, je commence par détruire toutes les ressources que l'objet gère, puis j'assigne, donc :

struct Animal
{
    int aNumber;
    int * buffer;
    Animal() { buffer = new int[128]; }
    Animal& operator= (Animal& other) 
    { 
      if (this != &other){
      delete [] buffer; 
      //this->~Animal();     // Je me demande si je peux appeler cela plutôt que de supprimer le tampon ici.
      aNumber = other.aNumber;
    }
    ~Animal() { delete[] buffer;}
};

La raison pour laquelle je pose cette question est que plutôt que de réécrire le code de suppression, je peux simplement le placer à un seul endroit. De plus, je ne pense pas que l'appel du destructeur libère la mémoire, donc lorsque j'assigne aNumber après avoir appelé le destructeur, je pense que c'est bon. Lorsque je dis que la mémoire n'est pas libérée, je veux dire par exemple que si j'avais un vector, et que le vector appelait l'opérateur d'assignation de copie pour vector[0], Animal vector[0] appellerait son propre destructeur puis assignerait aNumber, mais la mémoire est gérée par le vector (elle n'est pas désallouée). Ai-je raison de dire que la mémoire n'est pas désallouée ?

4voto

Après un appel de destructeur, la région de mémoire qui contenait l'objet est juste de la mémoire brute.

Vous ne pouvez pas utiliser le résultat en attribuant simplement aux membres apparents.

Il faut un appel de constructeur pour rétablir un objet là-bas.

Mais ne faites pas ça.

C'est rempli de dangers, un territoire absolument hostile mortel, et en plus c'est malodorant et sale.


Au lieu de

int* buffer;
Animal() { buffer = new int[128]; }

faire

vector buffer;

et agrandissez ce tampon au besoin en ajoutant des éléments, par exemple via push_back.

Un std::vector automatise la gestion de la mémoire pour vous, et le fait correctement de manière garantie. Pas de bugs. Beaucoup plus facile.


Par ailleurs, la signature

Animal& operator= (Animal& other)

vous permet seulement d'assigner à partir d'objets Animal non-const spécifiés avec des expressions lvalue (c'est-à-dire pas temporaires), car seules celles-ci peuvent être liées à la référence de l'argument formel non-const.

Une façon de résoudre cela est d'ajouter un const:

Animal& operator= (Animal const& other)

ce qui indique l'intention de ne pas modifier l'argument réel.

2voto

user2079303 Points 4916

Je me demande si je peux appeler [le destructeur] au lieu de supprimer le tampon ici.

Vous ne pouvez pas.

donc lorsque j'attribue un nombre après avoir appelé le destructeur, je pense que c'est OK

Ce n'est pas OK. Un appel explicite au destructeur met fin à la durée de vie de l'objet. Vous ne pouvez pas accéder aux membres d'un objet après la fin de sa durée de vie. Le comportement est indéfini.

Suis-je en train de dire que la mémoire n'est pas désallouée?

Vous avez raison, mais cela n'a pas d'importance.


La raison pour laquelle je pose cette question est pour éviter de réécrire le code de suppression, je peux simplement l'avoir à un seul endroit.

Cela peut être réalisé en écrivant une fonction qui libère les ressources, et en appelant cette fonction à la fois dans l'opérateur d'affectation et dans le destructeur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X