我需要手动关闭ifstream吗?

Edi*_*enz 187 c++ raii 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");
}
Run Code Online (Sandbox Code Playgroud)

我需要file.close()手动拨打电话吗?不应该ifstream使用RAII来关闭文件?

Ecl*_*pse 239

没有

这就是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().

  • +1 - 至少有一个人知道RAII的含义:-) (21认同)
  • 使用嵌套范围只是为了关闭文件是完全人为的 - 如果你想关闭它,请在它上面调用close(). (18认同)
  • 在C++中,嵌套作用域几乎从不必要.它们与代码的行为有关,特别是在抛出某些东西时.如果未来的维护者删除它们,他就不太了解C++. (9认同)
  • +1我不知道RAII处理那个......我猜你每天都学到新东西 (4认同)
  • 虽然,您可能会认为将对象的生命周期限制在必要的范围内意味着您不会意外访问已关闭的ifstream.但这有点做作. (3认同)
  • 我完全赞成尽可能地限制范围:-) (2认同)
  • 另外,请注意 basic_filebuf::close() 将始终刷新。只依赖RAII。不要让意外的异常改变您的代码。 (2认同)
  • 有时您确实需要手动调用close()来进行错误处理。 (2认同)
  • @ssfang(希望你不要介意这么晚的评论):1.:这个构造函数不是[标准](http://en.cppreference.com/w/cpp/io/basic_ifstream/basic_ifstream),所以必须是MSVC 扩展。2.:这种行为可以被认为是自然的:Stream关闭它自己打开的东西,不关闭它没有打开的东西...... (2认同)

Mar*_*ork 65

你需要关闭文件吗?
没有

你应该关闭文件吗?
要看.

您是否关心文件无法正确关闭时可能出现的错误情况?setstate(failbit)如果失败,请记住关闭呼叫.close()由于RAII,析构函数会自动为您调用,但由于对象不再存在,因此不会为您提供测试失败位的方法.


小智 14

我同意@Martin.如果您写入文件,数据可能仍然位于缓冲区上,并且在close()调用之前可能无法写入文件.如果不手动操作,您不知道是否存在错误.不向用户报告错误是一种非常糟糕的做法.


eri*_*tin 9

您可以允许析构函数完成其工作。但就像任何 RAII 对象一样,有时手动调用 close 可能会产生影响。例如:

#include <fstream>

using std::ofstream;

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

写入文件内容。但:

#include <stdlib.h>

#include <fstream>

using std::ofstream;

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

没有。这些是进程突然退出的罕见情况。崩溃的进程也可以做类似的事情。


Dim*_* C. 5

不,这是由ifstream析构函数自动完成的.您应该手动调用它的唯一原因是因为fstream实例具有大范围,例如,如果它是长生命类实例的成员变量.

  • 如果流允许例外,另一个原因可能是检查文件关闭错误并防止抛出析构函数. (4认同)