建议使用可能抛出的表达式初始化const变量的方法

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
  • 你必须编写嵌套代码

您知道哪种(好的,简短的和干净的)替代品?

M.M*_*M.M 2

该线程上有三个不错的选项,实际上没有任何其他选项。

这些情况假设我们正在初始化一个对象;要按原样初始化引用,请将技术应用于std::reference_wrapper, 或指针。


顺便说一句,我不会这么快就打折你的第一个代码示例。它比所有其他选项更简单,并且 C++ 中的常见建议是仅在异常情况下使用异常 - 您不希望成为函数契约的正常部分的事情。将它们用作快捷方式并不符合习惯。

换句话说,如果函数设计是在查找失败时不执行任何操作,那么抛出捕获对于函数来说是不必要的复杂化。您刚刚编写了一个更丑陋的 C 风格错误处理版本。

访问器的全部要点是,您的函数可以通过at()捕获来保持简单——可以将异常传播到更通用的错误处理程序。