假设我构造了一个RAII对象,并且该对象可能无法构造.我该如何处理?
try {
std::vector<int> v(LOTS);
// try scope ends here because that's what the catch is for
} catch( const std::bad_alloc& ) {
// ...
}
// v? what v?
Run Code Online (Sandbox Code Playgroud)
当然,默认构造函数std::vector不会抛出,这可能有所帮助,但这不是一般情况.一个构造函数可能会抛出.如果我想处理任何资源获取失败,如果它没有抛出,我怎么能这样做仍然能够继续?
编辑:为了澄清,我的问题是,如果资源无法获取,那么我可能想再试一次,依此类推.也许我可以尝试获取替代资源.
如果RAII构造函数抛出,则在抛出点之前绑定到RAII对象的所有资源都将被正确清理.C++规则的合理设计是为了保证这一点.
如果你的v构造因为一个抛出bad_alloc那么v在try块之前创建的任何RAII对象将被正确清理.
因此,如果您因此使用RAII,则不需要手动try/ catch类似,因为RAII对象会为您处理清理.如果由于某种原因确实需要它,在上面的情况下,你可以像下面这样使用swap.
std::vector<int> v;
try {
std::vector<int> vtry(LOTS);
v.swap(vtry); // no-throw
} catch( const std::bad_alloc& ) {
// ...
}
// v!
Run Code Online (Sandbox Code Playgroud)
取决于你的意思"继续".无论什么操作需要资源都会失败:这就是"需要"的意思.所以当你想在错误后继续,你最终可能会编写如下代码:
void something_using_RAII(thingummy &t) {
vector<int> v(t.size_required);
// do something using v
}
...
for each thingummy {
try {
something_using_RAII(this_thingummy);
} catch(const std::bad_alloc &) {
std::cerr << "can't manage that one, sorry\n";
}
}
Run Code Online (Sandbox Code Playgroud)
这就是为什么你应该只捕获例外情况,因为你可以用它们做一些有价值的事情(在这种情况下,报告失败并继续下一个事情).
如果要在失败时再次尝试,但仅当构造函数失败时,如果还有其他任何失败:
while(not bored of trying) {
bool constructor_failed = true;
try {
vector<int> v(LOTS);
constructor_failed = false;
// use v
} catch(...) {
if (!constructor_failed) throw;
}
}
Run Code Online (Sandbox Code Playgroud)
这或多或少是std::new_handler有效的 - 在类似循环的catch子句中调用处理程序,尽管不需要标志.
如果您想在失败时尝试不同的资源:
try {
vector<int> v(LOTS);
// use v
} catch(...) try {
otherthing<int> w(LOTS);
// use w
} catch(...) {
// failed
}
Run Code Online (Sandbox Code Playgroud)
如果"use v"和"use w"基本上是相同的代码,那么重构成一个函数并从两个地方调用它.你的功能在这一点上做了很多.
| 归档时间: |
|
| 查看次数: |
521 次 |
| 最近记录: |