在下面的代码中,会在哈希表中查找一个值,如果在映射中找不到键,我很困惑该怎么办。
返回迭代器以便调用方可以检查它更好吗?
提出一个例外更好吗?
还是做点别的?
这是代码:
#include <vector>
#include <algorithm>
#include <string>
#include <unordered_map>
struct binary_message
{
binary_message(std::initializer_list<unsigned char> data) : bytes_(data) {}
std::vector<unsigned char> bytes_;
};
// warning C4715: 'lookup_msg' : not all control paths return a value
static const binary_message& lookup_msg(const std::string& key) {
static std::unordered_map<std::string, binary_message> table =
{
{ "msg1", { 0x60, 0x23, 0x80, 0x02, 0x07, 0x80, 0xa1, 0x07, 0x06, 0x05, 0x2b, 0x0c, 0x00, 0x81, 0x5a, 0xbe,
0x14, 0x28, 0x12, 0x06, 0x07, 0x2b, 0x0c, 0x00, 0x82, 0x1d, 0x81, 0x48, 0xa0, 0x07, 0xa0, 0x05,
0x03, 0x03, 0x00, 0x08, 0x00 } },
{ "msg2", { 0x1, 0x2, 0x3 } },
{ "msg3", { 0x1, 0x2 } },
};
// what if key not found?
std::unordered_map<std::string, binary_message>::const_iterator it = table.find(key);
if (it != table.end())
return it->second;
//else
// ??? throw an exception? Something else? Or should I be returning a std::unordered_map<std::string, binary_message>::const_iterator?
}
int main()
{
const binary_message& msg7 = lookup_msg("msg1");
// do whatever with bytes
return 0;
}
这是Boost的一个很好的用例。可选:
static boost::optional<const binary_message&> lookup_msg(const std::string& key) {
...
if (it != table.end()) {
return it->second; // we have a value
}
else {
return boost::none; // we do not have a value
}
}
这里的想法是,返回类型本身知道它是否有值,没有歧义。
请注意,在这里返回迭代器并不是一个真正的选项,因为table
是函数的静态本地,所以调用方没有任何东西可以将其与之进行比较。
这是一个设计选择。你必须决定在没有错误的正常条件下,找不到条目是否可以接受。
例如,如果您的数据结构表示街道上的房屋,但并非街道上的所有空间都包含房屋,则找不到房屋不是错误,应该返回一个迭代器来与end(或可以为null的指针、标志或诸如此类的东西)进行比较
另一方面,如果街道上的每个无障碍空间都必须包含一栋房子,那么如果找不到房子,那么破例是一个合适的选择。
即使你选择第一种方法,如果你愿意的话,在街道的最大地址之外寻找房子仍然可以破例。
如果您不确定使用哪种方法,请考虑典型的用例。如果您抛出异常,您的用户将不需要手动检查每个请求是否找到了一个项目,如果找不到项目是导致他们无法跟踪的原因(错误、中止等),则简化了他们的工作。
另一方面,如果他们希望不定期找到一个项目,那么让他们每次都捕捉异常是令人讨厌的,也是低效的。
也没有什么可以阻止你提供两个功能,这两个功能可以处理找不到不同的物品,但不要想太多。:)
如果可以与容器的成员函数返回的结束元素进行比较,则将迭代器返回到结束元素非常有用。抛出异常很有用,因为如果返回指向坏内存的迭代器,访问该数据也可能抛出异常。您还可以像其他类似映射的类型那样返回一对结果(true/false)和迭代器结果。
迭代
std::unordered_map<std::string, binary_message>::const_iterator it = table.find(key);
if (it != table.end())
return it->second;
else
return table.end();
const binary_message& msg7 = lookup_msg("msg1");
if(msg7 == table.end())
// whatever
异常
std::unordered_map<std::string, binary_message>::const_iterator it = table.find(key);
if (it != table.end())
return it->second;
else
throw some_exception("Couldn't find element.");
配对
std::unordered_map<std::string, binary_message>::const_iterator it = table.find(key);
if (it != table.end())
return std::pair<bool, iterator_type>(true, it->second);
else
return std::pair<bool, iterator_type>(false, table.end());
const binary_message& msg7 = lookup_msg("msg1");
if(msg7.first)
// Do stuff
else
// Error out