Нужно ли вручную закрывать ifstream? - PullRequest
176 голосов
/ 14 апреля 2009

Нужно ли мне вручную звонить close() при использовании std::ifstream?

Например, в коде:

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

Нужно ли звонить file.close() вручную? Разве ifstream не должен использовать RAII для закрытия файлов?

Ответы [ 5 ]

228 голосов
/ 14 апреля 2009

НЕТ

Для этого и нужен RAII, пусть деструктор выполнит свою работу. Нет смысла закрывать его вручную, но это не C ++, а программирование на C с классами.

Если вы хотите закрыть файл до конца функции, вы всегда можете использовать вложенную область видимости.

В стандарте (27.8.1.5 Шаблон класса basic_ifstream) ifstream должен быть реализован с элементом basic_filebuf, содержащим фактический дескриптор файла. Он сохраняется как член, поэтому при разрушении объекта ifstream он также вызывает деструктор в basic_filebuf. И из стандарта (27.8.1.2) этот деструктор закрывает файл:

virtual ˜basic_filebuf();

Эффекты: Уничтожает объект класса basic_filebuf<charT,traits>. Звонки close().

61 голосов
/ 14 апреля 2009

Вам нужно закрыть файл?
NO

Стоит ли закрывать файл?
В зависимости.

Вам небезразличны возможные ошибки, которые могут возникнуть при неправильном закрытии файла? Помните, что закрытие звонков setstate(failbit), если это не удается. Деструктор вызовет для вас close() автоматически из-за RAII , но не оставит вам способа проверить бит сбоя, поскольку объект больше не существует.

11 голосов
/ 15 июля 2011

Я согласен с @Martin. Если вы записываете в файл, данные могут все еще находиться в буфере и могут не записываться в файл, пока не будет вызван close(). Не делая это вручную, вы не представляете, произошла ошибка или нет. Не сообщать пользователю об ошибках - очень плохая практика.

6 голосов
/ 15 апреля 2009

Нет, это делается автоматически деструктором ifstream. Единственная причина, по которой вы должны вызывать его вручную, заключается в том, что экземпляр fstream имеет большую область видимости, например, если это переменная-член экземпляра класса с длительным временем жизни.

4 голосов
/ 22 мая 2018

Вы можете позволить деструктору выполнять свою работу. Но, как и в случае любого объекта RAII, могут быть случаи, когда вызов close вручную может иметь значение. Например:

#include <fstream>

using std::ofstream;

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

записывает содержимое файла. Но:

#include <stdlib.h>

#include <fstream>

using std::ofstream;

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

нет. Это редкие случаи, когда процесс внезапно завершается. Процесс сбоя может сделать подобное.

...