我需要关闭std :: fstream吗?

Tob*_*ner 59 c++ fstream std ofstream

可能重复:
我是否需要手动关闭ifstream?

我是否需要调用fstream.close()或是fstream一个正确的RAII对象,在销毁时关闭流?

std::ofstream在方法中有一个本地对象.我可以假设退出此方法后文件总是关闭而不调用close吗?我找不到析构函数的文档.

Kon*_*lph 89

我认为以前的答案是误导性的.

fstream 一个合适的RAII对象,它在作用域的末尾自动关闭,并且在作用域结束时关闭时,完全没有必要close手动调用.

特别是,它不是"最佳实践",也没有必要刷新输出.

虽然Drakosha是正确的,但调用close让你有可能检查流的失败位,无论如何都没有人这样做.

在一个理想的世界中,人们可以stream.exception(ios::failbit)事先调用并处理在fstream析构函数中抛出的异常.但不幸的是,析构函数中的异常在C++中是一个破碎的概念,所以这不是一个好主意.

因此,如果要检查关闭文件是否成功,请手动执行(但仅限于此).

  • @Drakosha:确保将数据一直刷新到磁盘与"flush"或"close"保证完全不同.一般来说,最好的假设是`flush`将数据从进程中提取出来并进入操作系统级别,因此例如终止进程不会阻止数据被写入.没有可移植的API来确保数据被提交到持久存储,因为C++标准没有持久存储的概念,而不是作为文件系统(部分)呈现的其他存储. (7认同)
  • 我实际上每次检查关闭结果,因为我正在处理一个必须确保数据提交到磁盘的应用程序.此外,有点不合适,**关闭不能确保刷新**(至少在linux上),而且我不确定析构函数是否刷新.我实际上说它是冲洗和关闭的"最佳实践",并检查两者上的错误. (4认同)
  • 我也对 linux 的行为感到有些惊讶。fstream 析构函数需要调用 `close` 成员函数,`close` 需要“像通过 `fclose`”关闭,并且定义 `fclose` 来刷新流。所以析构函数当然应该冲洗,尽管如果存在插头被拉到机器上的风险,冲洗可能不一定会做你想要的。为此,您需要(非标准 C++)`fsync`。 (2认同)
  • @Highstaker 在自动完成的编程中手动做事绝对是一个坏习惯。在这种特殊情况下,它碰巧没有不良影响(除了添加无意义的代码行),但这不是一个值得遵守的重要原则。 (2认同)
  • @jrh 断开连接后关闭外部存储介质上的文件。这将导致关闭(和刷新)失败,但应用程序可以成功继续运行。 (2认同)

Dra*_*sha 6

要附加到Amy Lee的答案,最好手动完成,因为这样你也可以检查错误.

BTW,根据"关闭"手册页:

不检查close()的返回值是一个常见但严重的编程错误.很可能首先在最后的close()上报告先前write(2)操作的错误.关闭文件时不检查返回值可能会导致数据无声丢失.使用NFS和磁盘配额尤其可以观察到这种情况.

成功关闭并不能保证数据已成功保存到磁盘,因为内核会延迟写入.当流关闭时,文件系统刷新缓冲区并不常见.如果您需要确保数据是物理存储的,请使用fsync(2).(这取决于此时的磁盘硬件.)

  • 这是一个可怕的答案.`close()`不是`fstream :: close()`.根据规格,后者将始终冲洗.在网上很容易找到它. (8认同)
  • @GMan:这不是真的不在你手中,这取决于具体情况.至少你应该以某种方式告诉你的用户. (5认同)
  • @GMan:如果你没有检查错误,这意味着你误导你的用户数据在磁盘上而不是. (4认同)