当返回迭代器时,最好返回迭代程序类型还是实际对象
When returning an iterator, is it better to return iterator type or actual object
在下面的代码中,会在哈希表中查找一个值,如果在映射中找不到键,我很困惑该怎么办。
返回迭代器以便调用方可以检查它更好吗?
提出一个例外更好吗?
还是做点别的?
这是代码:
#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
- 如何获取std::result_of函数的返回类型
- 奇怪的结构&GCC&clang(void*返回类型)
- 如何建立使用模板函数的lambda函数的尾部返回类型
- 为什么与常规GCC不同,即使有"学究性错误",MinGW-GCC也能容忍丢失的返回类型
- 在没有定义返回类型的函数中返回布尔值,并将结果保存在无错误的char编译中-为什么
- 特征::矩阵<双精度,1,3> 结构类型函数中的返回类型函数
- 函数作为模板参数,是否对返回类型强制约束
- C++中函数的向量返回类型引发错误
- 检查函数返回类型是否与STL容器类型值相同
- 为什么返回类型中需要typename?C++
- <Windows>为什么 std::thread::native_handle 返回类型为"long long unsigned int"的值,而不是 void*(又名 HANDLE)?
- 警告:在函数返回类型 [-Wignore 限定符] 时忽略类型限定符
- 为什么 c++(g++) 不允许模板返回类型和函数名称之间有空格?
- 为什么返回类型的'const'限定符对标有 __forceinline/内联的函数没有影响?
- 推导 std::vector::back() 的返回类型
- 在 c++ 中将函数返回类型指定为模板参数
- 使用 SWIG 更改生成的 CS 函数中的返回类型
- QtQuick - qml:28:错误:未知方法返回类型:自定义类型
- 基于返回类型的转换和过载扣除
- 当返回类型声明为 ListNode 时,我们是否可以返回 false<T>*