web-dev-qa-db-fra.com

Dois-je fermer manuellement un ifstream?

Dois-je appeler manuellement close() lorsque j'utilise un std::ifstream?

Par exemple, dans le code:

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");
}

Dois-je appeler file.close() manuellement? ifstream ne devrait-il pas utiliser RAII pour la fermeture de fichiers?

179

NON

C’est à cela que sert RAII, laissez le destructeur faire son travail. Il n’ya pas de mal à le fermer manuellement, mais ce n’est pas la méthode C++, c’est la programmation en C avec des classes.

Si vous souhaitez fermer le fichier avant la fin d'une fonction, vous pouvez toujours utiliser une portée imbriquée.

Dans la norme (27.8.1.5 Modèle de classe basic_ifstream), ifstream doit être implémenté avec un membre basic_filebuf Contenant le descripteur de fichier réel. Il est tenu en tant que membre de sorte que lorsqu'un objet ifstream est détruit, il appelle également le destructeur sur basic_filebuf. Et à partir de la norme (27.8.1.2), ce destructeur ferme le fichier:

virtual ˜basic_filebuf();

Effects: Détruit un objet de classe basic_filebuf<charT,traits>. Appelle close().

232
Eclipse

Avez-vous besoin de fermer le fichier?
NON

Devez-vous fermer le fichier?
Dépend.

Vous souciez-vous des éventuelles erreurs pouvant survenir si le fichier ne se ferme pas correctement? Rappelez-vous que les appels rapprochés setstate(failbit) s’ils échouent. Le destructeur appellera close() pour vous automatiquement à cause de RAII mais ne vous laissera pas le moyen de tester le bit d'échec en tant qu'objet no. existe plus longtemps.

62
Martin York

Je suis d'accord avec @Martin. Si vous écrivez dans le fichier, il est possible que les données restent sur une mémoire tampon et ne soient pas écrites dans le fichier avant que close() ne soit appelé. Sans le faire manuellement, vous ne savez pas s'il y a eu une erreur ou non. Ne pas signaler les erreurs à un utilisateur est une très mauvaise pratique.

12
Mark Edwards

Non, cela est fait automatiquement par le destructeur ifstream. La seule raison pour laquelle vous devriez l'appeler manuellement est que l'instance fstream a une grande portée, par exemple s'il s'agit d'une variable membre d'une instance de classe longue durée.

6
Dimitri C.

Vous pouvez laisser le destructeur faire son travail. Mais comme pour tout objet RAII, il peut arriver que l’appel de fermeture manuelle puisse faire la différence. Par exemple:

#include <fstream>

using std::ofstream;

int main() {
  ofstream ofs("hello.txt");
  ofs << "Hello world\n";
  return 0;
}

écrit le contenu du fichier. Mais:

#include <stdlib.h>

#include <fstream>

using std::ofstream;

int main() {
  ofstream ofs("hello.txt");
  ofs << "Hello world\n";
  exit(0);
}

ne pas. Ce sont des cas rares où un processus se termine soudainement. Un processus bloquant pourrait faire la même chose.

4
ericcurtin