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

Ответ 1

NO

Это то, к чему относится RAII, пусть деструктор выполняет свою работу. Нет никакого вреда при закрытии его вручную, но это не С++-путь, он программируется на 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) вызовы setstate(failbit) если он терпит неудачу. Деструктор вызовет close() для вас автоматически из-за RAII, но не оставит вам способа проверить бит сбоя, так как объект больше не существует.

Ответ 3

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

Ответ 4

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

Ответ 5

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

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