【问题标题】:Can a file stream destructor throw an exception in C++?文件流析构函数可以在 C++ 中引发异常吗?
【发布时间】:2017-12-24 10:43:02
【问题描述】:

文件流析构函数能否抛出异常,例如,如果文件关闭操作失败?

   auto f = new std::ofstream("data.txt");
   f->exceptions(std::ofstream::failbit | std::ofstream::badbit);
   ...
   delete f; // May throw?     

我可以通过手动关闭流来防止此类异常吗?

   auto f = new std::ofstream("data.txt");
   f->exceptions(std::ofstream::failbit | std::ofstream::badbit);
   ...
   f->close();
   delete f; // May throw?     

【问题讨论】:

标签: c++ exception destructor throw filestreams


【解决方案1】:

从析构函数中抛出是危险的,应该避免。 C++ 标准库的任何对象都不会从其析构函数中抛出。 C++ 语言隐含地假定析构函数被声明为noexcept

事实上,这是std::basic_filebuf<>::close()std::basic_filebuf<>::~std::basic_filebuf() 之间的唯一区别:后者调用close() 但捕获任何异常而不重新抛出。因此,如果您想发现关闭基础文件的问题,您可以显式调用ofstream::rdbuf()->close()。然而ofstream::close() 有效地调用rdbuf()->close() 并捕获任何异常。在这种情况下,它会设置 failbitiff 您已相应地设置了流的异常掩码(通过 ofstream::exceptions(),就像您在问题中所做的那样)抛出 @987654323 类型的(不同)异常@。

因此,总结一下:

  • 如果您使用 RAII(即析构函数)关闭文件,则不会 异常将被传播出析构函数,即使 基础文件无法干净地关闭。在这种情况下, 将设置失败位。
  • 如果你明确地close()std::ofstream,那么,根据流的异常掩码,在遇到关闭文件的问题时可能会抛出std::ios_base::failure

【讨论】:

  • @Holt 谢谢。我已编辑我的答案以反映您的评论。
猜你喜欢
  • 2010-11-14
  • 2013-10-30
  • 2014-07-29
  • 1970-01-01
  • 2018-11-26
  • 2017-08-16
  • 2012-04-11
  • 1970-01-01
  • 2014-07-06
相关资源
最近更新 更多