web-dev-qa-db-fra.com

Quels destructeurs sont exécutés lorsque le constructeur lève une exception?

En C++, si un constructeur lève une exception, quels destructeurs sont exécutés?

En particulier, cela fait-il une différence si l'exception se produit pendant la liste d'initialisation ou le corps?

Et l'héritage et les membres? Vraisemblablement, toutes les constructions terminées sont détruites. Si seuls quelques membres sont construits, seuls ceux-ci sont-ils détruits? S'il existe plusieurs héritages, tous les constructeurs terminés sont-ils détruits? L'héritage virtuel change-t-il quelque chose?

72
WilliamKF

si un constructeur lève une exception, quels destructeurs sont exécutés?

Destructeurs de tous les objets entièrement créés dans cette portée.

Cela fait-il une différence si l'exception se trouve pendant la liste d'initialisation ou le corps?

Tous les objets terminés seront détruits.
Si le constructeur n'a jamais été complètement appelé, l'objet n'a jamais été construit et ne peut donc pas être détruit.

Qu'en est-il de l'héritage et des membres? Vraisemblablement, toutes les constructions terminées sont détruites. Si seuls quelques membres sont construits, seuls ceux-ci sont-ils détruits? S'il existe plusieurs héritages, tous les constructeurs terminés sont-ils détruits? L'héritage virtuel change-t-il quelque chose?

Toutes les constructions terminées sont détruites. Oui, seuls les objets entièrement créés sont détruits.

Bonne lecture:

Échecs du constructeur par Herb Sutter

Surtout, j'aime la partie où il explique:

En termes biologiques, la conception a eu lieu - le constructeur a commencé -, mais malgré tous les efforts, elle a été suivie d'une fausse couche - le constructeur n'a jamais couru à terme (ination).

Par ailleurs, c'est pourquoi un destructeur ne sera jamais appelé si le constructeur n'a pas réussi - il n'y a rien à détruire. "Il ne peut pas mourir, car il n'a jamais vécu." Notez que cela fait de la phrase "un objet dont le constructeur a levé une exception" vraiment un oxymore. Une telle chose est encore moins qu'un ancien objet ... elle n'a jamais vécu, n'a jamais été, n'a jamais respiré son premier.

70
Alok Save

En C++, si un constructeur lève une exception, quels destructeurs sont exécutés?

Tous les objets dont l'exécution a été exécutée par les constructeurs.

En particulier, cela fait-il une différence si l'exception se produit pendant la liste d'initialisation ou le corps?

Non. Tous les membres entièrement construits avant l'exception verront leurs destructeurs fonctionner. Le membre qui a lancé pendant la construction et tous les autres membres non construits pas verront leurs destructeurs fonctionner. L'ordre de construction des membres est bien défini et vous savez donc exactement ce qui se passera étant donné que vous connaissez le point du lancer d'exception.

Et qu'en est-il de l'héritage et des membres?

La même règle s'applique.

Vraisemblablement, toutes les constructions terminées sont détruites.

Oui

Si seuls quelques membres sont construits, seuls ceux-ci sont-ils détruits?

Oui

S'il existe plusieurs héritages, tous les constructeurs terminés sont-ils détruits?

Oui

L'héritage virtuel change-t-il quelque chose?

Non.
Mais remarque: l'héritage virtuel affecte l'ordre dans lequel les constructeurs sont appelés. Si vous ne savez pas comment la commande est définie, cela peut ne pas être intuitif tant que vous n'aurez pas recherché les règles exactes.

19
Martin York

Tout objet créé dans une portée locale laissé à cause du constructeur sera détruit. La gestion de l'exécution remonte la pile, appelant des destructeurs, jusqu'à ce qu'elle trouve un gestionnaire.

Si l'exception est levée par un constructeur, les destructeurs de tous les sous-objets entièrement construits seront appelés. De plus, si le constructeur faisait partie d'une expression new, l'opérateur de suppression de placement approprié sera appelé s'il existe.

4
James Kanze