Espacios de nombres
Variantes
Acciones

Adquisición de Recursos es Inicialización (RAII)

De cppreference.com
< cpp‎ | language
 
 
Lenguaje C++
Temas generales
Control de flujo
Instrucciones de ejecución condicionales
Instrucciones de iteración (bucles)
Declaraciones de salto
Funciones
Declaración de funciones
Declaración de funciones lambda
Especificador inline
Especificación de excepciones(hasta C++20)
Especificador noexcept(C++11)
Excepciones
Espacios de nombres
Tipos
Especificadores
decltype(C++11)
auto(C++11)
alignas(C++11)
Especificadores de duración de almacenamiento
Inicialización
Expresiones
Representaciones alternas
Literales
Booleanos - Enteros - De punto flotante
De carácter - De cadena - nullptr(C++11)
Definidos por el usuario(C++11)
Utilidades
Atributos(C++11)
Tipos
Declaración de typedef
Declaración de alias de tipo(C++11)
Conversiones
Conversiones implícitas - Conversiones explícitas
static_cast - dynamic_cast
const_cast - reinterpret_cast
Asignación de memoria
Clases
Propiedades de funciones específicas de la clase
Funciones miembro especiales
Plantillas
Misceláneos
 

La Adquisición de Recursos es Inicialización o RAII por sus siglas en inglés Resource Acquisition Is Initialization, es una técnica de programación de C++[1][2] que vincula la duración de un recurso que tiene que ser adquirido antes de ser usado (asignación de memoria de montículo, hilo de ejecución, abrir un socket, abrir un archivo, tomar un mutex, espacio de disco, conexión a una base de datos–cualquier cosa que tenga un suministro limitado) a la duración de un objeto.

RAII garantiza que el recurso se encuentre disponible a cualquier función que pueda accesar el objeto (la disponibilidad de recursos es una invariante de clase, eliminando así pruebas redundantes en tiempo de ejecución). También garantiza que todos los recursos se liberen cuando la duración de su objeto controlador llegue a su fin, en orden inverso al orden de adquisición. De la misma manera, si la adquisición de recursos falla (el constructor egresa con una excepción), todos los recursos adquiridos por cada dato miembro completamente construido y por el subobjeto base se liberan en orden inverso al de inicialización. Esto toma ventaja de las características centrales del lenguaje (duración del objeto, salida de ámbito, orden de inicialización y desenredo de pila) para eliminar fugas de recursos y garantizar seguridad de excepciones. Otro nombre para esta técnica es Administración de Recursos Vinculados a un Ámbito (SBRM por sus siglas en inglés), debido al caso de uso básico donde la duración de un objeto RAII termina debido a que sale de ámbito.

RAII puede resumirse de la manera siguiente:

  • encapsula cada recurso en una clase, donde
  • el constructor adquiere el recurso y establece todas las invariantes de clase o lanza una excepción si no puede hacerse;
  • el destructor libera el recurso y nunca lanza una excepción;
  • siempre usa el recurso mediante una instancia de una clase RAII que bien
  • el objeto RAII mismo tiene duración de almacenamiento automática o temporal, o
  • tiene duración que está vinculada por la duración de un objeto automático o temporal.

La semántica de movimiento hace posible transferir de manera segura la propiedad entre dos objetos, a lo largo de ámbitos, dentro y fuera de hilos, manteniendo la seguridad del recurso.

Las clases con pares de funciones open()/close(), lock()/unlock(), o funciones miembro init()/copyFrom()/destroy() son ejemplo típicos de clases no-RAII:

std::mutex m;   void malo(){ m.lock();// adquiere el mutex f();// si f() lanza una excepción, el mutex nunca se liberaif(!everything_ok())return;// retorno temprano, el mutex nunca se libera m.unlock();// si malo() llega a esta instrucción, el mutex se libera}   void bueno(){std::lock_guard<std::mutex> lk(m);// clase RAII: adquisición del mutex es inicialización f();// si f() lanza una excepción, el mutex se liberaif(!everything_ok())return;// retorno temprano, el mutex se libera}// si bueno() retorna normalmente, el mutex se libera

[editar]La biblioteca estándar

Las clases de la biblioteca de C++ que administran sus propios recursos siguen la técnica RAII: std::string, std::vector, std::thread, y muchas otras adquieren sus recursos en los constructores (que lanzan excepciones si hay errores), los liberan en sus destructores (que nunca lanzan), y no requieren limpieza explícita.

Además, la biblioteca estándar oferece varios envolventes RAII para administrar recursos proporcionados por el usuario:

[editar]Notas

RAII no se aplica a la administración de recursos que no se adquieren antes de usarse: tiempo de la CPU, núcleos, y capacidad de la caché, capacidad de la reserva de entropía, ancho de banda de la red, consumo de potencia eléctrica, memoria de la pila.

[editar]Referencias

  1. RAII en las preguntas frecuentes de C++, por Stroustrup
  2. Directrices Centrales de C++ E.6 "Usa RAII para prevenir fugas"
close