Muss ich einen ifstream manuell schließen?

201

Muss ich manuell anrufen, close()wenn ich a verwende std::ifstream?

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

Muss ich file.close()manuell anrufen ? Sollte nicht ifstreamGebrauch machen RAII zum Schließen von Dateien?

Edison Gustavo Muenz
quelle

Antworten:

251

NEIN

Dafür ist RAII gedacht. Lassen Sie den Destruktor seine Arbeit machen. Es schadet nicht, es manuell zu schließen, aber es ist nicht die C ++ - Methode, es programmiert in C mit Klassen.

Wenn Sie die Datei vor dem Ende einer Funktion schließen möchten, können Sie immer einen verschachtelten Bereich verwenden.

In der Norm (27.8.1.5 Klassenvorlage basic_ifstream) ifstreamist mit einem basic_filebufMember zu implementieren , das das eigentliche Dateihandle hält. Es wird als Mitglied gehalten, sodass beim Zerstören eines ifstream-Objekts auch der Destruktor aufgerufen wird basic_filebuf. Und nach dem Standard (27.8.1.2) schließt dieser Destruktor die Datei:

virtual ˜basic_filebuf();

Effekte: Zerstört ein Klassenobjekt basic_filebuf<charT,traits>. Anrufe close().

Finsternis
quelle
4
+1 Ich wusste nicht, dass RAII damit
umgeht
21
Die Verwendung eines verschachtelten Bereichs zum Schließen der Datei ist völlig künstlich. Wenn Sie sie schließen möchten, rufen Sie close () auf.
3
Möglicherweise können Sie jedoch argumentieren, dass die Beschränkung der Lebensdauer des Objekts auf den erforderlichen Bereich bedeutet, dass Sie nicht versehentlich auf einen geschlossenen ifstream zugreifen. Aber das ist ein bisschen erfunden.
Eclipse
9
In C ++ sind verschachtelte Bereiche fast nie unnötig. Sie haben alles mit dem Verhalten des Codes zu tun, besonders wenn etwas wirft. Wenn ein zukünftiger Betreuer sie entfernt, kennt er C ++ nicht sehr gut.
Elliot Cameron
2
Manchmal müssen Sie close()zur Fehlerbehandlung manuell aufrufen .
ks1322
71

Müssen Sie die Datei schließen?
NEIN

Sollten Sie die Datei schließen?
Hängt davon ab.

Interessieren Sie sich für mögliche Fehlerbedingungen, die auftreten können, wenn die Datei nicht ordnungsgemäß geschlossen wird? Denken Sie daran, dass Anrufe schließen, setstate(failbit)wenn dies fehlschlägt. Der Destruktor ruft close()Sie aufgrund von RAII automatisch auf , lässt Ihnen jedoch keine Möglichkeit, das Fehlerbit zu testen, da das Objekt nicht mehr vorhanden ist.

Martin York
quelle
14

Ich stimme @Martin zu. Wenn Sie in die Datei schreiben, befinden sich die Daten möglicherweise noch in einem Puffer und werden möglicherweise erst in die Datei geschrieben, wenn sie close()aufgerufen werden. Ohne dies manuell zu tun, haben Sie keine Ahnung, ob ein Fehler aufgetreten ist oder nicht. Es ist eine sehr schlechte Praxis, einem Benutzer keine Fehler zu melden.

Mark Edwards
quelle
5

Nein, dies wird automatisch vom ifstreamDestruktor durchgeführt. Der einzige Grund, warum Sie es manuell aufrufen sollten, ist, dass die fstreamInstanz einen großen Umfang hat, beispielsweise wenn es sich um eine Mitgliedsvariable einer langlebigen Klasseninstanz handelt.

Dimitri C.
quelle
4
Ein weiterer Grund könnte darin bestehen, Fehler beim Schließen von Dateien zu überprüfen und das Auslösen des Destruktors zu verhindern, wenn Ausnahmen für den Stream zulässig sind.
Daniel Langr
4

Sie können dem Destruktor erlauben, seine Arbeit zu erledigen. Aber genau wie bei jedem RAII-Objekt kann es vorkommen, dass ein manueller Aufruf zum Schließen einen Unterschied macht. Beispielsweise:

#include <fstream>

using std::ofstream;

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

schreibt Dateiinhalte. Aber:

#include <stdlib.h>

#include <fstream>

using std::ofstream;

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

nicht. Dies sind seltene Fälle, in denen ein Prozess plötzlich beendet wird. Ein Absturzprozess könnte ähnlich ablaufen.

Ericcurtin
quelle