文件流析构函数是否可以抛出异常,例如,如果文件关闭操作失败?
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++标准库的任何对象都不会从其析构函数中抛出。C++语言隐式假定析构函数声明为noexcept
。
事实上,这是std::basic_filebuf<>::close()
和std::basic_filebuf<>::~std::basic_filebuf()
之间的唯一区别:后者调用close()
但捕获任何异常而不重新抛出。因此,如果要捕获关闭基础文件时出现的问题,可以显式调用ofstream::rdbuf()->close()
。但是,ofstream::close()
有效地调用rdbuf()->close()
并捕获任何异常。在这种情况下,它会设置failbit
,并且如果您相应地设置了流的异常掩码(通过ofstream::exceptions()
,就像您在问题中所做的那样(抛出类型std::ios_base::failure
的(不同的(异常。
因此,总结一下:
- 如果使用 RAII(即析构函数(关闭文件,则不会 异常将从析构函数中传播出去,即使 无法完全关闭基础文件。在这种情况下, 将设置故障位。
- 如果显式
close()
std::ofstream
,则根据流的异常掩码,在关闭文件时遇到问题时可能会抛出std::ios_base::failure
。