【问题标题】:Do I need to manually close an ifstream?我需要手动关闭 ifstream 吗?
【发布时间】:2010-10-19 09:07:59
【问题描述】:

使用std::ifstream时是否需要手动调用close()

例如在代码中:

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

【问题讨论】:

    标签: c++ ifstream raii


    【解决方案1】:

    没有

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

    如果你想在函数结束之前关闭文件,你总是可以使用嵌套范围。

    在标准(27.8.1.5 类模板 basic_ifstream)中,ifstream 将通过一个持有实际文件句柄的basic_filebuf 成员来实现。它作为一个成员保存,因此当 ifstream 对象析构时,它还会在 basic_filebuf 上调用析构函数。从标准 (27.8.1.2) 来看,该析构函数会关闭文件:

    virtual ˜basic_filebuf();

    效果:销毁basic_filebuf&lt;charT,traits&gt; 类的对象。致电close()

    【讨论】:

    • +1 我不知道 RAII 能处理这个问题……我猜你每天都会学到一些新东西
    • 使用嵌套作用域来关闭文件完全是人为的——如果你想关闭它,请在其上调用 close()。
    • 尽管您可能会争辩说,将对象的生命周期限制在必要的范围内意味着您不会意外访问已关闭的 ifstream。但这有点做作。
    • 在 C++ 中,嵌套范围几乎是不必要的。它们与代码的行为有关,尤其是在抛出异常时。如果将来的维护者删除它们,他就不太了解 C++。
    • 有时您确实需要手动调用close() 进行错误处理。
    【解决方案2】:

    您需要关闭文件吗?
    没有

    您应该关闭文件吗?
    视情况而定。

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案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);
        }
        

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

        【讨论】:

          【解决方案5】:

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

          【讨论】:

          • 如果流允许异常,另一个原因可能是检查文件关闭错误并防止抛出析构函数。
          猜你喜欢
          • 2012-12-11
          • 2013-10-22
          • 2013-01-10
          • 1970-01-01
          • 2017-07-10
          • 1970-01-01
          • 2015-02-04
          • 2013-07-31
          • 1970-01-01
          相关资源
          最近更新 更多