在重构一些旧代码时,一个繁琐的多层映射开发内部被std::undordered_multiset
取代。
多级地图就像[string_key1,string_val]
。应用了一个复杂的算法来从string_val
导出密钥,并导致重复的string_val
存储在地图中但具有不同的密钥。
最终,在应用程序的某个时刻,迭代了多级映射以获取string_val
及其出现次数。
替换为std::unordered_multilevelset
,只插入了string_val
。它似乎比拥有std::map<std::string,int>
和检查 - 检索 - 更新每个插入的计数器简单得多。
我想要做的是检索其插入元素的出现次数,但我没有前面的键。所以我迭代了桶,但我的程序在创建字符串时崩溃了。
// hash map declaration
std::unordered_multiset<std::string> clevel;
// get element and occurences
for (size_t cbucket = clevel->bucket_count() - 1; cbucket != 0; --cbucket)
{
std::string cmsg(*clevel->begin(cbucket));
cmsg += t_str("times=") + \
std::to_string(clevel->bucket_size(cbucket));
}
我不明白这里发生了什么,试图调试它,但我不知何故堆栈(溢出?):)。程序在std::string cmsg(*it);
答案 0 :(得分:2)
您应该考虑multiset
实际上如何作为哈希表。例如,阅读此introduction您应该注意到哈希映射实际上预先分配了它们的内部桶,并且优化了桶的数量。
因此,如果您插入元素“hello”,您可能会获得许多已创建的存储桶,但只有与hash("hello")
对应的存储桶实际上会有一个您可以取消引用的元素。其余的将被视为无效。
取消引用迭代器到每个存储桶的开头会产生SEGV,这就是你的情况。
要解决这种情况,每次开始时都应该检查结束。
for (size_t cbucket = clevel->bucket_count() - 1; cbucket != 0; --cbucket)
{
auto it = clevel->begin(cbucket);
if (it != clevel->end(cbucket))
{
std::string cmsg(*it);
cmsg += t_str("times=") + \
std::to_string(clevel->bucket_size(cbucket));
}
}