提问人:Roddy 提问时间:7/5/2010 最后编辑:Roddy 更新时间:1/13/2021 访问量:22765
为什么 C++ STL iostreams 不“异常友好”?
Why are C++ STL iostreams not "exception friendly"?
问:
我习惯了 Delphi VCL 框架,其中 TStreams 在错误时抛出异常(例如找不到文件,磁盘已满)。我正在移植一些代码以改用 C++ STL,并且被 iostreams 捕获,默认情况下不会抛出异常,而是设置 badbit/failbit 标志。
两个问题...
答:为什么会这样 - 对于一个从第一天起就有异常的语言来说,这似乎是一个奇怪的设计决定?
b:如何最好地避免这种情况?我可以按照我的预期制作垫片类,但这感觉就像重新发明轮子。也许有一个 BOOST 库可以以更理智的方式做到这一点?
答:
C++ 从第一天起就没有例外。“C with classes”始于 1979 年,并于 1989 年添加了例外。同时,该库早在 1984 年就编写了(后来在 1989 年成为(后来在 1991 年由 GNU 重新实现)),它只是不能在一开始就使用异常处理。
streams
iostreams
裁判:
您可以使用
.exceptions
方法启用例外。
// ios::exceptions
#include <iostream>
#include <fstream>
#include <string>
int main () {
std::ifstream file;
file.exceptions(ifstream::failbit | ifstream::badbit);
try {
file.open ("test.txt");
std::string buf;
while (std::getline(file, buf))
std::cout << "Read> " << buf << "\n";
}
catch (ifstream::failure& e) {
std::cout << "Exception opening/reading file\n";
}
}
评论
file.close()
- 你需要吗?我以为他们足够聪明,可以接近毁灭......???
flush()
closing()
swap()
每当抛出异常时,都需要考虑异常安全性。所以没有例外,没有例外,没有例外——安全令人头疼。
Iostreams 还支持异常。但抛出异常是可选的。您可以通过设置
exceptions (failbit | badbit | eofbit)
Iostreams 允许你接受异常和无期望行为。
评论
正如 Kenny 所说,如果需要,您可以启用例外。但通常情况下,当发生错误时,I/O 需要某种恢复式的编程,这不容易通过使用异常来支持 - 在输入操作后测试流的状态要简单得多。我实际上从未见过任何在 I/O 上使用异常的 C++ 代码。
评论
while(!completed) {try { doIo();completed=true;} catch (...) { if (promptAbortRetry("whoops!") == ABORT) completed = true;}
好了,现在是“回答我自己的问题”的时候了......
首先,感谢 KennyTM 的历史。正如他所说,C++从第一天起就没有例外,所以iostreams的“异常”处理后来被附加也就不足为奇了。
其次,正如 Neil B 所指出的,在输入格式转换错误上出现异常将是一个巨大的痛苦。这让我很惊讶,因为我正在考虑将 iostreams 作为一个简单的文件系统包装层,而我根本没有考虑过这种情况。
第三,BOOST似乎确实带来了一些东西:Boost.IOStreams。如果我理解正确的话,它们处理流的低级 I/O 和缓冲方面,让常规的 c++ IOStreams 库处理转换问题。Boost.IOStreams 确实以我所期望的方式使用异常。如果我理解正确的话,肯尼的例子也可以是这样的:
#include <ostream>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/stream.hpp>
int main () {
boost::iostreams::stream_buffer <boost::iostreams::file_source> buf("test.txt");
std::istream file(&buf);
try {
std::string buf;
while (std::getline(file, buf))
std::cout << "Read> " << buf << "\n";
}
catch (std::ios_base::failure::failure e) {
std::cout << "Exception opening/reading file\n";
}
std::cout.flush();
file.close();
return 0;
}
我认为在这个版本中,应该抛出“找不到文件”之类的东西,但是“istream”错误将由 badbit/failbit 报告。
评论