如果构造器的资源分配部分例如RAII套接字包装失败,我是否只抛出异常并完成处理?还是我应该使用 std::fstream
seems to do it的方式,在构造对象之后需要检查is_open()
的地方?
前者似乎更符合“资源分配就是初始化”的名称,但是为什么标准库基本上使您在使用对象之前检查错误代码?
我指的是basic_fstream
的引用页面上的示例(解释为,已添加注释):
int main() {
std::string filename = "test.bin";
std::fstream s(filename);
if (!s.is_open()) { // should my socket class require the user to do this?
std::cout << "failed to open " << filename << '\n';
} else {
// ... use it
}
}
最佳答案
建议采取的措施是在施工过程中发生的任何故障上抛出异常。引用C++ FAQ:
Q. How can I handle a constructor that fails?
A. Throw an exception.
Constructors don’t have a return type, so it’s not possible to use return codes. The best way to signal constructor failure is therefore to throw an exception. If you don’t have the option of using exceptions, the “least bad” work-around is to put the object into a “zombie” state by setting an internal status bit so the object acts sort of like it’s dead even though it is technically still alive.
如果施工涉及RAII,则构造函数还有责任在抛出之前清理所有已分配的资源。
Q. How should I handle resources if my constructors may throw exceptions?
A. Every data member inside your object should clean up its own mess.
If a constructor throws an exception, the object’s destructor is not run. If your object has already done something that needs to be undone (such as allocating some memory, opening a file, or locking a semaphore), this “stuff that needs to be undone” must be remembered by a data member inside the object.
至于为什么
std::fstream
构造函数不引发异常并默认使用fallback选项(将对象置于“僵尸”状态)的原因,即历史与便利的结合,在Why are C++ STL iostreams not “exception friendly”?的答案中有更好的解释。
关于c++ - 创建RAII类时应如何处理错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63894509/