我需要手动关闭ifstream吗?


201

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关闭文件吗?

Answers:


251

没有

这就是RAII的目的,让析构函数完成其工作。手动关闭它没有害处,但这不是C ++方式,而是使用类在C中进行编程。

如果要在函数结束之前关闭文件,则可以始终使用嵌套作用域。

在标准(27.8.1.5类模板basic_ifstream)中,ifstream将使用basic_filebuf拥有实际文件句柄的成员来实现。它作为成员保存,以便当ifstream对象销毁时,它还会在上调用销毁器basic_filebuf。根据标准(27.8.1.2),该析构函数将关闭文件:

virtual ˜basic_filebuf();

效果:销毁class对象basic_filebuf<charT,traits>。来电close()


4
+1我不知道RAII会如何处理...我想你每天都在学习新知识
TStamper

21
仅使用嵌套作用域来关闭文件是完全人为的-如果要关闭文件,请对其调用close()。

3
虽然,您可能会争辩说将对象的生存期限制在必要的范围内,这意味着您不会意外访问封闭的ifstream。但这有点人为。

9
在C ++中,嵌套作用域几乎从来没有必要。它们与代码的行为有关,尤其是在某些情况下。如果将来的维护者将其删除,他将不太了解C ++。
艾略特·卡梅隆

2
有时您确实需要close()手动调用以进行错误处理。
ks1322'8

71

您需要关闭文件吗?
没有

您应该关闭文件吗?
要看。

您是否担心文件无法正确关闭时可能发生的错误情况?请记住,setstate(failbit)如果失败,则关闭呼叫。析构函数会调用close()自动为您因为RAII但不会离开你作为测试对象已不存在失败位的方法。


14

我同意@Martin。如果您写入文件,则数据可能仍位于缓冲区上,直到close()被调用才可能被写入文件。如果不手动进行操作,则不知道是否存在错误。不向用户报告错误是非常糟糕的做法。


5

不,这是由ifstream析构函数自动完成的。您应该手动调用它的唯一原因是因为fstream实例的作用域很大,例如,如果它是寿命很长的类实例的成员变量。


4
如果流允许例外,则另一个原因可能是检查文件关闭错误并防止抛出析构函数。
丹尼尔·兰格

4

您可以允许析构函数完成其工作。但是,就像任何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);
}

不。在极少数情况下,进程突然退出。崩溃过程可能会执行类似操作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.