Preciso manualmente perto de uma ifstream?
Pergunta
Preciso close()
chamada manualmente quando eu uso um std::ifstream
?
Por exemplo, no 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");
}
Preciso chamada file.close()
manualmente? Não deve ifstream
fazer uso RAII para fechamento de arquivos?
Solução
NO
Isto é o que RAII é para, deixe o destruidor fazer o seu trabalho. Não há mal nenhum em fechá-lo manualmente, mas não é o C ++ maneira, está programando em C com classes.
Se você quiser fechar o arquivo antes do fim de uma função você sempre pode usar um escopo aninhado.
No padrão (27.8.1.5 classe de modelo basic_ifstream), ifstream
está a ser implementado com um membro basic_filebuf
segurando a alça arquivo real. Ele é tido como um membro de modo que quando um objeto ifstream destrói, ele também chama o destruidor sobre basic_filebuf
. E a partir do padrão (27.8.1.2), que destructor fecha o arquivo:
virtual ˜basic_filebuf();
Efeitos: Destrói um objeto de
basic_filebuf<charT,traits>
classe. Chamadasclose()
.
Outras dicas
Você precisa fechar o arquivo?
NO
Se você fechar o arquivo?
Depende.
Você se importa com as possíveis condições de erro que podem ocorrer se o arquivo não se fecha corretamente? Lembre-se que triz setstate(failbit)
se ele falhar. O destruidor vai chamar close()
automaticamente para você por causa de RAII , mas não vai deixar você uma maneira de testar o bit falhar como o objeto não existe mais.
Concordo com @ Martin. Se você escrever para o arquivo, os dados ainda podem estar sentado em um buffer e não pode ficar gravada no arquivo até close()
é chamado. Sem fazê-lo manualmente, você não tem idéia se houve um erro ou não. Não relatar erros para um usuário é uma prática muito ruim.
Não, isso é feito automaticamente pelo destruidor ifstream
. A única razão que você deve chamá-lo manualmente, é porque a instância fstream
tem um grande alcance, por exemplo, se é uma variável membro de uma instância de long classe vida.
Você pode permitir que o destruidor de fazê-lo do trabalho. Mas, como qualquer objeto RAII pode haver momentos em que chamar perto manualmente pode fazer a diferença. Por exemplo:
#include <fstream>
using std::ofstream;
int main() {
ofstream ofs("hello.txt");
ofs << "Hello world\n";
return 0;
}
escreve o conteúdo do arquivo. Mas:
#include <stdlib.h>
#include <fstream>
using std::ofstream;
int main() {
ofstream ofs("hello.txt");
ofs << "Hello world\n";
exit(0);
}
não. Estes são raros casos em que um processo de repente sai. Um processo de bater podia fazer semelhante.