L'acquisition de ressources est l'initialisation signifie que les objets doivent se prendre en charge en tant que package complet et ne pas s'attendre à ce qu'un autre code indique à une instance "hé au fait, vous allez bientôt être nettoyé - veuillez ranger maintenant". Cela signifie généralement qu'il y a quelque chose de significatif dans le destructeur. Cela signifie également que vous écrivez une classe spécifiquement pour gérer les ressources, sachant que dans certaines circonstances difficiles à prévoir, comme des exceptions levées, vous pouvez compter sur l'exécution de destructeurs.
Supposons que vous vouliez écrire du code où vous allez changer le curseur Windows en un curseur d'attente (sablier, beignet non fonctionnel, etc.), faites votre travail, puis changez-le à nouveau. Et dites aussi que «faites votre truc» pourrait lever une exception. La manière RAII de le faire serait de créer une classe dont le ctor positionnerait le curseur en attente, dont la seule "vraie" méthode ferait ce que vous voudriez faire, et dont le dtor redéfinirait le curseur. Les ressources (dans ce cas, l'état du curseur) sont liées à la portée d'un objet. Lorsque vous acquérez la ressource, vous initialisez un objet. Vous pouvez compter sur la destruction de l'objet si des exceptions sont levées, ce qui signifie que vous pouvez compter sur le nettoyage de la ressource.
Bien utiliser RAII signifie que vous n'avez pas besoin finally
. Bien sûr, il repose sur une destruction déterministe, que vous ne pouvez pas avoir en Java. Vous pouvez obtenir une sorte de destruction déterministe en C # et VB.NET avec using
.
RAII consiste en partie à décider quand un objet devient responsable de son propre nettoyage - la règle étant que l'objet devient responsable si et quand l'initialisation de son constructeur se termine. La symétrie de l'initialisation et du nettoyage, constructeur et destructeur, signifie que les deux ont des liens étroits l'un avec l'autre.
Un point de RAII est d'assurer la sécurité des exceptions - que l'application reste cohérente lorsque des exceptions sont levées. À première vue, cela est trivial - lorsqu'une exception entraîne la fermeture d'une étendue, les variables locales de cette étendue doivent être détruites.
Mais que se passe-t-il si le lancement d'exception se produit dans un constructeur?
Eh bien, l'objet n'a pas été entièrement construit, il ne peut donc pas être détruit en toute sécurité. Le constructeur doit avoir essayé des blocs au besoin pour s'assurer que tous les nettoyages nécessaires sont effectués avant que l'exception ne soit propagée. Une fois que l'exception se propage en dehors de la portée où l'objet a été construit, il n'y aura plus d'appel de destructeur, car l'objet n'a pas été construit en premier lieu.
Considérez en particulier les constructeurs des données de membre à l'intérieur de l'objet en cours de destruction. Si l'un de ces éléments lève une exception, votre code de constructeur principal ne s'exécutera pas du tout - mais un code qui forme une partie implicite de ce constructeur aura. Tous les membres qui ont été construits avec succès seront automatiquement détruits. Tous les membres qui n'ont pas été construits (y compris celui qui a levé l'exception) ne le sont pas.
Donc, fondamentalement, RAII est une politique qui garantit que tout ce qui est entièrement construit sera détruit en temps opportun, en particulier en présence de levées d'exceptions, et que tout objet soit entièrement construit ou ne l'est pas (il n'y a pas de demi- des objets construits que vous ne savez pas comment nettoyer en toute sécurité). Les ressources allouées sont également libérées. Et une grande partie du travail est automatisée, donc le programmeur n'a pas à s'en soucier trop.
la source