在map / unordered_map中使用find与at

时间:2016-08-03 05:07:41

标签: c++ exception-handling containers

以下显示了查找unordered_map元素的两种方法,如果所需键的元素不存在,则会引发一些错误条件。他们基本上做同样的事情。是否有理由偏爱另一个,或者仅仅是风格问题?

void foo()
{
    unordered_map<string, int> lookup;

    // Method 1. Lookup using find.
    const auto i = lookup.find("myKey");
    if (i == lookup.end()) {
        // Some error condition...
    }
    else {
        // Do something with i...
    }

    // Method 2. Lookup using try / catch.
    try {
        const auto& ele = lookup.at("myKey");
        // Do something with ele...
    }
    catch (out_of_range& e) {
        // Some error condition...
    }
}

3 个答案:

答案 0 :(得分:5)

就我个人而言,我永远不会使用例外。例外是真正特殊的。它们的强大之处在于允许您编写代码而无需进行持续的本地错误检查但是没有在容器中找到元素(通常)不是错误,它只是两种可能中的一种。

作为一项规则,我会说使用异常如果没有找到元素意味着你必须中止整个函数/操作/子系统。不要用它来检查个别陈述结果。

答案 1 :(得分:2)

这些方法具有完全不同的返回值,因此它们在不同情况下很有用。

例如,如果您需要值本身,则可以同时使用它们,因为您可以轻松地从迭代器中获取值。但是你不能这样做:at返回一个值引用,不能在O(1)时间内“转换”为迭代器。从值引用“获取”迭代器的唯一方法是使用ie find迭代映射。因此,如果需要值,请调用at,如果需要迭代器,请调用findat也应该更快,因为它不处理中间迭代器对象,并且不需要解除引用操作符调用。

另一个问题是异常可用性。由于某种原因,项目的代码样式可能会禁止例外,甚至可能被编译器标志禁用。在这种情况下,使用find是唯一的选择。

答案 2 :(得分:1)

由于异常处理意味着对优化器的限制,因此第二种方法在大多数情况下会产生更大的二进制文件。此外,某些系统上/不需要进行异常处理(甚至禁用)。

如果您正在开发可能被其他人使用的库,请选择第一种方法。