La adquisición de recursos es la inicialización significa que los objetos deben cuidarse a sí mismos como un paquete completo y no esperar que otro código le diga a una instancia "oye, por cierto, te limpiarán pronto, ordena ahora". Por lo general, significa que hay algo significativo en el destructor. También significa que escribe una clase específicamente para administrar recursos, sabiendo que bajo ciertas circunstancias difíciles de predecir, como las excepciones, puede contar con la ejecución de destructores.
Supongamos que desea escribir un código en el que va a cambiar el cursor de Windows a un cursor de espera (reloj de arena, donut de no funcionar, etc.), haga sus cosas y luego vuelva a cambiarlo. Y diga también que "haga sus cosas" podría generar una excepción. La forma RAII de hacerlo sería hacer una clase cuyo ctor haya puesto el cursor en espera, cuyo único método "real" hiciera lo que quisieras que hiciera, y cuyo dtor hizo retroceder el cursor. Los recursos (en este caso, el estado del cursor) están vinculados al alcance de un objeto. Cuando adquiere el recurso, inicializa un objeto. Puede contar con la destrucción del objeto si se lanzan excepciones, y eso significa que puede contar con la limpieza del recurso.
Usar bien RAII significa que no necesitas finally
. Por supuesto, se basa en la destrucción determinista, que no puede tener en Java. Puede obtener una especie de destrucción determinista en C # y VB.NET con using
.
RAII se trata en parte de decidir cuándo un objeto se hace responsable de su propia limpieza; la regla es que el objeto se vuelve responsable si y cuando se completa la inicialización del constructor. La simetría de inicialización y limpieza, constructor y destructor, significa que los dos tienen vínculos estrechos entre sí.
Un punto de RAII es garantizar la seguridad de las excepciones: que la aplicación siga siendo coherente cuando se lanzan excepciones. A primera vista, esto es trivial: cuando una excepción hace que salga un ámbito, las variables locales en ese ámbito deben destruirse.
Pero, ¿qué sucede si el lanzamiento de excepción ocurre dentro de un constructor?
Bueno, el objeto no se ha construido completamente, por lo que no se puede destruir con seguridad. El constructor debe tener bloques de prueba según sea necesario para garantizar que se realicen las limpiezas necesarias antes de que se propague la excepción. Una vez que la excepción se propague fuera del alcance donde se construyó el objeto, no habrá una llamada de destructor, porque el objeto no se construyó en primer lugar.
Considere en particular los constructores de datos de miembros dentro del objeto que se está destruyendo. Si uno de esos arroja una excepción, su código de constructor principal no se ejecutará en absoluto, pero sí lo tendrá algún código que forme parte implícita de ese constructor. Cualquier miembro que se haya construido correctamente se destruirá automáticamente. Los miembros que no fueron construidos (incluido el que arrojó la excepción) no lo son.
Básicamente, RAII es una política que garantiza que todo lo que se construya completamente se destruirá de manera oportuna, particularmente en presencia de lanzamientos de excepción, y que cualquier objeto se construya completamente o no (no hay mitad) objetos construidos que no puedes saber cómo limpiar de forma segura). Los recursos que se asignan también se liberan. Y gran parte del trabajo está automatizado, por lo que el programador no tiene que preocuparse demasiado por ello.
fuente