Un jour avant, j'ai fait face à cette question lors d'une interview. Alors, guide-moi. Comment nettoyer les ressources initialisées si une exception est levée du constructeur en C++?Comment nettoyer les ressources initialisées si une exception est levée du constructeur en C++
Répondre
L'astuce consiste à utiliser RAII (l'acquisition de ressources est l'initialisation) pour gérer les ressources.
Si vous avez des membres de pointeur, utilisez des pointeurs intelligents au lieu de pointeurs bruts qui effectueront automagiquement le travail de nettoyage une fois qu'une exception est levée du constructeur.
Bonne lecture:
Herb Sutter's excellent GotW article "Construction Failures"
+1 pour le lien – Dialecticus
Utilisez les membres de données qui libèrent les ressources quand ils sont détruits (aka RAII).
Par exemple:
struct TwoStrings {
std::string string1;
std::string string2;
TwoStrings(const std::string &input) : string1(input) {
if (!input[1] == ':') {
throw std::logic_error('not a Windows absolute path');
// yes, absolute paths can begin \\, this is a toy example
}
if (input.back() == '\\') {
string2 = input;
} else {
string2 = input + "\\";
}
}
};
Si le constructeur lance (soit logic_error
ou bad_alloc
), le membre de données déjà initialisé string1
est détruit, ce qui libère la ressource. Pour cette raison, string2
est également détruit, mais si le constructeur lance alors string2
doit toujours être vide, donc cela n'a pas d'effet particulier.
string
est un exemple de classe qui gère les ressources, mais il y en a beaucoup d'autres. Les plus flexibles d'entre eux sont appelés "pointeurs intelligents" et peuvent être configurés pour gérer à peu près n'importe quelle ressource, pas seulement des tableaux de caractères auto-alloués comme string
.
Lorsqu'une exception est levée, la pile est déroulée jusqu'au point de capture. En conséquence, tout ce qui avait été construit en elle est détruit. Il est donc important de placer chaque ressource sensible dans une classe dont le destructeur s'occupe de l'élimination de la ressource associée. Si la ressource est un objet affecté par le tas, les pointeurs intelligents font exactement cela (supprimer l'objet point après sa destruction), si la ressource est un fichier ouvert, un flux le ferme après destruction. Tout le reste nécessite un wrapper personnalisé. Mais notez que les nombreuses "ressources" sont représentées par des gestionnaires qui sont eux-mêmes void *. Ceci permet également d'utiliser smart poitner, en initialisant ensuite avec la ressource allouée et en spécifiant une fonction de suppression. Ce que la technique joue mieux est beaucoup plus une question de goût et d'opportunité.
La meilleure façon de le faire est: Allouer toutes les ressources dans les constructeurs et désaffecter n'importe lequel dans les destructeurs.
Les modèles en C++ sont très utiles dans ce but car nous pouvons rendre la création d'objets atomique.
Vous devez trouver des exemples et un peu plus d'explications car vous voyez que cette question a déjà assez bien répondu à quelques-uns. –
- 1. Quel code est exécuté si une exception est levée?
- 2. Comment tester si une exception est levée dans AngularJS
- 3. Comment la dernière levée Exception contient une exception précédemment levée?
- 4. Ne pas détruire l'instance EJB si une exception est levée
- 5. Comment puis-je voir les types par lesquels une exception InvalidCastException est levée en C#?
- 6. Comment attraper une exception levée dans ctypes?
- 7. C++ stacktrace de la fonction une exception est levée?
- 8. Objective-C Exception non levée
- 9. Quand une exception Java est-elle levée
- 10. spring mvc: détecter si une exception a été levée lors du chargement du contexte
- 11. La mémoire allouée à un objet est-elle automatiquement supprimée si une exception est levée dans un constructeur?
- 12. état LHS après exception est levée
- 13. Android: Leaked IntentReceiver exception est levée même si j'appelle unregisterReceiver
- 14. programme d'interruption dans le débogueur lorsque C++ exception est levée
- 15. Exception levée lorsque l'ordre de déclaration des ressources a changé
- 16. L'exception C++ n'est pas levée pour le constructeur par défaut?
- 17. La présence du constructeur dans une applet jette une exception
- 18. Exception levée par le constructeur invoqué dans com.google.android.youtube.api.jar.client.RemoteEmbeddedPlayer
- 19. Comment est-ce que je décris une méthode qui n'a aucun effet secondaire si une exception est levée pendant l'exécution?
- 20. Exception levée dans un verrou C# 2
- 21. Objectif-C: NSMutableString replaceCharactersInRange levée Exception
- 22. Le HttpContext.Current est-il éliminé même si une exception est levée?
- 23. Levée d'une exception pythonienne
- 24. assertRaises échoue, même exception est levée
- 25. f # exception levée en désordre dans une boucle
- 26. Bind Exception non levée
- 27. Nettoyer les URL de ressources dans Rails
- 28. Destructeur pas appelée lorsqu'une exception est levée
- 29. Quand les variables statiques sont-elles initialisées en C#?
- 30. Comment attraper une exception Lua en C#
Pourquoi est-ce être proche a été voté? Ceci est un Q valide. Ne votez pas Q parce que vous ne l'aimez pas ou que vous ne le comprenez pas.Faites voter seulement et seulement s'il est admissible à la fermeture conformément à la politique de SO. –