fra*_*ans 5 c++ exception-handling const
您可能知道这样的情况,您只想分配一个const带有表达式的()变量,该表达式可能会失败(抛出)(例如container.at()),这会迫使您编写样板代码:
void foo(const string &key) {
auto it = data_store.find(key);
if (it == data_store.end()) {
return;
}
const auto & element = it->second;
...
go on with `element`...
...
}
Run Code Online (Sandbox Code Playgroud)
在Python中,您可以编写如下代码:
def foo(name):
try:
element = data_store[key]
except KeyError:
return
..
go on with `element`
..
Run Code Online (Sandbox Code Playgroud)
..因为你没有引入那些无用的额外it只是为了检查存在而没有噪音.
如果C++ try不会引入变量作用域,你可以使用at():
void foo(const string &key) {
try {
const auto & element = data_store.at(key);
} catch (const out_of_range &) {
return;
}
...
go on with `element`...
...
}
Run Code Online (Sandbox Code Playgroud)
如果你不想放弃constness并保持你的代码干净,那么去这里的方法是什么?
如果lambdas只能有一个try/ catchbody你可以写
void foo(const string &key) {
const auto & element = [&] () -> T try {
return data_store.at(key);
} catch () {
return;
} ();
...
go on with `element`...
...
}
Run Code Online (Sandbox Code Playgroud)
对类似问题的一些答案建议try/ catch阻止所有代码:
void foo(const string &key) {
try {
const auto & element = data_store.at(key);
...
go on with `element`...
...
} catch (const out_of_range &) {
return;
} catch (some other exception) {
...
} catch (some other exception) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
但我不喜欢这个,原因有三个:
at(),它的catch块out_of_range您知道哪种(好的,简短的和干净的)替代品?
该线程上有三个不错的选项,实际上没有任何其他选项。
这些情况假设我们正在初始化一个对象;要按原样初始化引用,请将技术应用于std::reference_wrapper, 或指针。
顺便说一句,我不会这么快就打折你的第一个代码示例。它比所有其他选项更简单,并且 C++ 中的常见建议是仅在异常情况下使用异常 - 您不希望成为函数契约的正常部分的事情。将它们用作快捷方式并不符合习惯。
换句话说,如果函数设计是在查找失败时不执行任何操作,那么抛出捕获对于函数来说是不必要的复杂化。您刚刚编写了一个更丑陋的 C 风格错误处理版本。
访问器的全部要点是,您的函数可以通过不at()捕获来保持简单——可以将异常传播到更通用的错误处理程序。