以下程序迭代unordered_map尝试找到最佳元素但不完全返回预期结果:
#include <iostream>
#include <unordered_map>
using namespace std;
struct Item
{
int val;
};
int main() {
unordered_map<int, Item> itemMap;
itemMap[0] = {0};
itemMap[1] = {1};
itemMap[2] = {2};
itemMap[3] = {3};
const Item* bestItem = nullptr;
int bestVal = -1;
for (const pair<int, Item>& item : itemMap)
{
if (item.second.val > bestVal)
{
bestVal = item.second.val;
bestItem = &item.second;
}
}
cout << "best val: " << bestVal << " best item: " << bestItem->val;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
运行此程序打印出来:
best val: 3 best item: 0
这似乎是因为value_typea unordered_map是,std::pair<const Key, T>但我们正在迭代const pair<int, Item>.果然改变这个const pair<const int, Item>导致:
best val: 3 best item: 3
但是,如果我们将类型更改itemMap为std::map:
map<int, Item> itemMap
然后,如果我们迭代const pair<int, Item>或const pair<const int, Item>得到相同的结果无关紧要:
best val: 3 best item: 3
尽管value_type的std::map仍然是std::pair<const Key, T>.但为什么?
问题可以归结为"为什么未定义的行为会为不同的容器提供不同的结果?",答案是"因为它未定义".
不那么轻浮:你可能会看到最后一次迭代的价值,这在订购的情况下是最大的map,但可能是任何东西unordered_map.
根据你的描述,我想你明白为什么它是未定义的:一个const引用可以绑定到一个临时的,所以如果类型不完全匹配,它会这样做,而不是绑定到map元素本身.引用,因此临时,在循环中作用域,因此在外部不可用.你对它的悬空指针将最终指向重用该内存的任何东西 - 在这种情况下,这很可能是在循环的后续迭代中的相同变量.
正如您在评论中所说,使用auto &&(或者,可能更好auto const &),以便类型推导确保类型匹配,并且引用直接绑定到地图元素.然后指针将指向一个map元素,并且在循环外仍然有效.