unordered_map:如果key不在map中,返回什么?

时间:2013-10-04 21:40:29

标签: c++ semantics unordered-map

作为这个问题的前言,我不得不说我是一名Java程序员,因此更习惯于使用Java中的Maps而不是C ++中的语义。在Java中,它很常见,并且在Map中查找键时会返回null。我正在将一些代码翻译成c ++,并尝试在与unordered_map交互时找到c ++的处理方式。

具体来说,我有一个包含unordered_map的类。我没有将映射直接暴露给客户端代码,而是有2个包装函数,一个用于将键/值对放入映射,另一个用于检索指定键的值,即:

void set_tag_value(string tag, string value);

string& get_tag_value(string tag);

如果我使用unordered_map.at()来检索值,那么它将抛出我的代码需要捕获的异常,或者允许它传播到客户端代码。 (尽管如此,传播例外似乎对我不友好)。

也许替代方法是将返回值更改为string*类型,如果未找到则返回NULL(这是Java的方式),但是用户需要检查NULL(这是也不那么友好)。

所以我的问题有两部分:

  1. 处理失败查找的开发人员友好方式是什么,返回值有用(异常,NULL,空字符串或其他内容)?

  2. 在我的代码中,当您期望它可能找不到密钥,at()和catch异常,或者查找并检查iterator == map.end()时,哪个map up up方法更常用? (这部分问题是我只是想学习c ++的做事方式)。

  3. 感谢您的任何建议!

2 个答案:

答案 0 :(得分:13)

在我看来,最好不要返回指向您保密的地图内容的指针,因为如果地图发生变化,指针可能会失效。

我会让函数返回成功代码(bool)并传递对字符串的引用,以便在找到时实际返回值。例如,

bool get_tag_value(const string& tag, string& value)
{
    auto t = my_map.find(tag);
    if (t == my_map.end()) return false;
    value = t->second;
    return true;
}

请注意,如果未找到密钥,unordered_map::at()将抛出,unordered_map::find()将返回无效的迭代器(unordered_map::end()) - 因此您可以避免以这种方式处理异常。

如果你想坚持返回一个字符串,那么只要找不到密钥就返回一个空字符串(return string();)。

答案 1 :(得分:1)

根据您使用boost的意愿,我会考虑以下两个选项:

返回一个指针:

/* const? */ string* get_tag_value_ptr(const string& tag)
{
    auto it = theMap.find(tag);
    if (it != theMap.end()) {
        return &it->second;
    }

    return nullptr;
}

返回可选参考:

boost::optional</* const? */ string&> get_tag_value_opt(const string& tag)
{
    auto it = theMap.find(tag);
    if (it != theMap.end()) {
        return it->second;
    }

    return boost::none;
}

希望我们很快就会std::optional,尽管它已被推迟到C ++ 14。

这些检索方法无需复制地图中的值。返回via参数意味着复制值。我想这取决于你的要求。