16

作为这个问题的前言,我不得不说我是一名 Java 程序员,因此比 C++ 更习惯 Java 中的 Maps 语义。null在 Java 中,当在 Map 中查找键时,它很常见并且预期会返回。我正在将我们的一些代码翻译成 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() 并捕获异常或查找并检查迭代器 == map.end() 时,使用哪种映射查找方法更为典型?(这部分问题是我只是想学习 c++ 做事的方式)。

感谢您的任何建议!

4

2 回答 2

14

在我看来,最好不要返回指向您保持私有的地图内容的指针,因为如果地图更改,指针可能会失效。

我会让函数返回一个成功代码 ( 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()如果找不到键,while 将抛出,unordered_map::find()返回无效的迭代器 ( unordered_map::end()) - 因此您可以避免以这种方式处理异常。

如果您想坚持返回一个字符串,那么return string();如果找不到该键,则只需返回一个空字符串 ( )。

于 2013-10-04T21:43:46.263 回答
1

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

返回一个指针:

/* 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 推迟了。

这些检索方法不需要从映射中复制值。通过 out 参数返回意味着复制该值。我想这取决于你的要求是什么。

于 2013-10-04T21:48:03.127 回答