作为这个问题的前言,我不得不说我是一名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(这是也不那么友好)。
所以我的问题有两部分:
处理失败查找的开发人员友好方式是什么,返回值有用(异常,NULL,空字符串或其他内容)?
在我的代码中,当您期望它可能找不到密钥,at()和catch异常,或者查找并检查iterator == map.end()时,哪个map up up方法更常用? (这部分问题是我只是想学习c ++的做事方式)。
感谢您的任何建议!
答案 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参数意味着复制值。我想这取决于你的要求。