Нужно ли вручную закрывать ifstream?

мне нужно вручную позвонить 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() вручную? Не должен!--4--> использовать RAII для закрытия файлов?

5 ответов


нет

это то, для чего предназначен 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().


вам нужно закрыть файл?
Нет!--2-->

следует ли закрыть файл?
Зависит.

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


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


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


вы можете позволить деструктору выполнять свою работу. Но, как и любой объект 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);
}

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