2009-04-14 16 views
138

¿Debo llamar manualmente al close() cuando uso un std::ifstream?¿Debo cerrar manualmente un ifstream?

Por ejemplo, en el código:

std::string readContentsOfFile(std::string fileName) { 

    std::ifstream file(fileName.c_str()); 

    if (file.good()) { 
     std::stringstream buffer; 
     buffer << file.rdbuf(); 
     file.close(); 

     return buffer.str(); 
    } 
    throw std::runtime_exception("file not found"); 
} 

¿Es necesario llamar file.close() manualmente? ¿No debería ifstream hacer uso de RAII para cerrar archivos?

Respuesta

182

NO

Esto es lo que es para RAII, que el destructor haga su trabajo. No hay daño al cerrarlo manualmente, pero no es la forma C++, es la programación en C con clases.

Si desea cerrar el archivo antes del final de una función, siempre puede usar un ámbito anidado.

En el estándar (plantilla de clase 27.8.1.5 basic_ifstream), ifstream se implementará con un miembro basic_filebuf con el controlador de archivo real. Se mantiene como miembro de modo que cuando un objeto ifstream se destruye, también llama al destructor en basic_filebuf. Y a partir de la norma (27.8.1.2), que cierra el archivo destructor:

virtual ˜basic_filebuf();

Efectos: Destruye un objeto de clase basic_filebuf<charT,traits>. Llamadas close().

+12

+1 - Al menos uno que sabe lo que significa RAII :-) – Milan

+3

+1 No sabía que RAII maneja eso ... Supongo que aprenderá algo nuevo todos los días – TStamper

+13

Usar un alcance anidado solo para cerrar el archivo es completamente artificial: si quieres cerrarlo, llama a close() en él. –

43

¿Necesita cerrar el archivo?
NO

¿Debe cerrar el archivo?
Depende.

¿Te preocupan las posibles condiciones de error que podrían producirse si el archivo no se cierra correctamente? Recuerde que close calls setstate (failbit) si falla. El destructor llamará a close() automáticamente por RAII pero no le dejará una forma de probar el bit de falla ya que el objeto ya no existe.

4

No, esto se hace automáticamente por el destructor ifstream. La única razón por la que debe llamarlo manualmente es porque la instancia de fstream tiene un gran alcance, por ejemplo, si es una variable miembro de una instancia de clase de vida larga.

+0

Otro motivo podría ser comprobar los errores de cierre de archivo y evitar lanzar el destructor, si se permiten excepciones con la corriente. –

8

Estoy de acuerdo con @Martin. Si escribe en el archivo, los datos aún pueden estar almacenados en un búfer y es posible que no se graben en el archivo hasta que se llame al close(). Sin hacerlo manualmente, no tienes idea de si hubo un error o no. No reportar errores a un usuario es una muy mala práctica.

Cuestiones relacionadas