2012-10-04 4 views
6

Algún día antes me enfrenté a esta pregunta en una entrevista. Así que solo guíame.Cómo limpiar los recursos inicializados si se lanza una excepción desde el constructor en C++

¿Cómo se limpian los recursos inicializados si se lanza una excepción desde el constructor en C++?

+0

¿Por qué está siendo tan cercano este voto? Esta es una Q válida. No cierres las Q porque no te gusta o no la entiendes. Ciérrala solo y solo si cumple con los requisitos para el cierre según la política de SO. –

Respuesta

6

El truco es usar RAII (adquisición de recursos es inicialización) para administrar recursos.

Si tiene miembros de puntero, utilice punteros inteligentes en lugar de punteros sin procesar que automáticamente realizarán el trabajo de limpieza una vez que se genere una excepción desde el constructor.

Buena lectura:
Herb Sutter's excellent GotW article "Construction Failures"

+0

+1 para el enlace – Dialecticus

1

miembros Uso de datos que liberan los recursos cuando son destruidos (también conocido como RAII).

Por ejemplo:

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 el constructor lanza (ya sea logic_error o bad_alloc), entonces el miembro de datos inicializado ya-string1 se destruye, liberando el recurso. Para ese asunto, también se destruye string2, pero si el constructor tira, entonces string2 todavía debe estar vacío, por lo que no tiene ningún efecto particular.

string es un ejemplo de una clase que gestiona recursos, pero hay muchos otros. Los más flexibles de ellos se denominan "punteros inteligentes" y se pueden configurar para administrar prácticamente cualquier recurso, no solo las matrices autoasignadas de caracteres como string.

1

Cuando se lanza una excepción, la pila se desenrolla hasta el punto de captura. Como consecuencia, todo lo que se había construido se destruye.

El punto es, entonces, envuelva todos los recursos sensibles en una clase cuyo destructor se encarga de la eliminación del recurso asociado.

Si el recurso es un objeto asignado en el montón, los punteros inteligentes hacen exactamente eso (eliminar el objeto puntiagudo después de su destrucción); si el recurso es un archivo abierto, una secuencia lo cierra después de la destrucción. Todo lo demás requiere un contenedor personalizado.

Pero tenga en cuenta que los muchos "recursos" están representados por manejadores que son themselve void *. Esto permite usar también poitner inteligente, inicializando luego con el resoure asignado y especificando una función de eliminación.

Lo que la técnica juega mejor es mucho más una cuestión de gusto y oportunidad.

1

La mejor manera de hacerlo es: Asigne los recursos en los constructores y desasigne cualquiera de los destructores.

Las plantillas en C++ son muy útiles para este fin, ya que podemos hacer que la creación de objetos sea atómica.

+0

Tienes que encontrar ejemplos y un poco más de explicación ya que esta pregunta ya ha sido respondida bastante bien por pocos. –

Cuestiones relacionadas