Question

Aujourd'hui, j'ai vu un code hérité. Dans le destructeur, une instruction du type " supprime ". Je pense que cet appel sera récursif. Pourquoi ça marche?

J'ai effectué une recherche rapide sur Y !, j'ai découvert que s'il était nécessaire de restreindre la création d'un objet de pile à l'utilisateur, nous pouvons rendre destructor privé et fournir une interface pour supprimer l'instance. Dans l'interface fournie, nous devons appeler delete sur ce pointeur.

Existe-t-il d'autres situations pour utiliser de telles déclarations?

Était-ce utile?

La solution

" supprimer cette " est couramment utilisé pour les objets comptés en référence. Pour un objet compté en référence, la décision du moment de la suppression est généralement placée sur l'objet lui-même. Voici un exemple de ce à quoi une méthode Release ressemblerait [1].

int MyRefCountedObject::Release() {
  _refCount--;
  if ( 0 == _refCount ) {
    delete this;
    return 0;
  }
  return _refCount;
}

Les objets COM ATL sont un excellent exemple de ce modèle.

[1] Oui, je réalise que ce n'est pas sécurisé.

Autres conseils

delete this n'est pas valide dans un destructeur. Il peut être utilisé ailleurs. Mais ce n'est que rarement une bonne idée. La structure wxWidgets l’utilise pour leur classe de thread. Il a un mode dans lequel, lorsque le thread termine l'exécution, il libère automatiquement les ressources système et lui-même (l'objet wxThread). Je l’ai trouvé très ennuyeux, car de l’extérieur, vous ne pouvez pas savoir s’il est valide de le renvoyer ou non. Vous ne pouvez plus appeler une fonction comme IsValid , car l’objet n’existe pas. Cela ressemble au principal problème de supprimer ce , mis à part le problème suivant: il ne peut pas être utilisé pour des objets non dynamiques.

Si vous le faites, assurez-vous de ne toucher aucun membre de données ou d'appeler plus aucune fonction de membre sur l'objet que vous avez supprimé de cette façon. Mieux vaut le faire en tant que dernière instruction dans une fonction non virtuelle, protégée ou privée. L'appel de suppression est également valide dans une fonction virtuelle et / ou publique, mais je limiterais la visibilité de la méthode.

La la FAQ C ++ contient une entrée à ce sujet. Devis standard C ++ sur ma réclamation ci-dessus ( 3.8p5 ):

  

Avant le début de la vie d'un objet, mais après l'attribution du stockage que celui-ci occupera ou après la fin de la vie d'un objet et avant la réutilisation ou la libération de l'objet occupé, tout pointeur faisant référence à jusqu’à l’emplacement de stockage où l’objet sera ou a été localisé ne peut être utilisé que de manière limitée. [...] Si l'objet sera ou était d'un type classe avec un destructeur non trivial, et que le pointeur est utilisé comme opérande d'une expression delete, le programme a un comportement indéfini.

La durée de vie se termine lorsque le destructeur de l'objet commence son exécution. Notez qu'il existe des exceptions aux règles qui suivent après ce paragraphe pour les objets en construction et en destruction (vous êtes autorisé à accéder à des membres de données non statiques, par exemple), détaillées dans 12.7 .

Il y avait de bonnes raisons de faire cela au début de C ++. Par exemple, l'auto-suppression d'un objet compté en référence (comme dit JaredPar). Autant que je sache, ils se sont tous avérés être une mauvaise idée à long terme.

Dans une liste doublement chaînée, il est possible de supprimer un nœud sans faire référence à une structure externe, telle que la "liste" de haut niveau objet. Il est donc raisonnable que chaque nœud gère sa propre désallocation (éventuellement associée à une méthode statique complémentaire pour gérer l’allocation initiale à partir du même pool de mémoire). Dans ce cas, il peut être judicieux que l’objet noeud se supprime lui-même (à la demande de l’utilisateur).

void RemoveAndDeallocate()
{
    LinkedListNode *current_prev = prev, *current_next = next;
    current_prev->next = current_next;
    current_next->prev = current_prev;
    delete this;
}

Bien qu'il soit également raisonnable qu'un nœud soit dissocié d'une liste et lié à une autre liste sans libérer de mémoire, il n'est donc pas souhaitable qu'une seule opération de suppression libère la mémoire de manière inconditionnelle.

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