C++ 为什么重用std::map.find';在已擦除的条目上返回的迭代器是否提供有效的键和随机值?

C++ 为什么重用std::map.find';在已擦除的条目上返回的迭代器是否提供有效的键和随机值?,c++,dictionary,stl,iterator,find,C++,Dictionary,Stl,Iterator,Find,我在代码中遇到了一个问题,我使用了以下映射方法序列find(k),erase(k),find(k),两次都访问了find返回的迭代器的第一个和第二个成员 这使我能够正确地对照map.find(k)=map.end()进行检查。但如果忽略这一点,幕后会发生什么 即使将find返回的迭代器与.end()进行比较,其计算结果为true,它。第一个(旧键)和它。第二个(随机值)仍然可以访问 编译器版本:g++(Ubuntu 8.4.0-1ubuntu1~18.04)8.4.0 最小工作示例 #包括 #包

我在代码中遇到了一个问题,我使用了以下映射方法序列
find(k)
erase(k)
find(k)
,两次都访问了find返回的迭代器的第一个和第二个成员

这使我能够正确地对照map.find(k)=map.end()进行检查。但如果忽略这一点,幕后会发生什么

即使将find返回的迭代器与
.end()
进行比较,其计算结果为
true
它。第一个
(旧键)和
它。第二个
(随机值)仍然可以访问

编译器版本:g++(Ubuntu 8.4.0-1ubuntu1~18.04)8.4.0

最小工作示例

#包括
#包括
int main(int argc,char const*argv[]
{
标准:map测试图;
测试映射插入(标准::对(1,2));
测试映射插入(标准::对(2,1));
printf(“带有%lu键值对的映射:(1,2)和(2,1)。
在映射上迭代:\n“,test_map.size());
for(const auto&it:test_map)
{
printf(“找到的条目-k:%lu,v:%lu\n”,it.first,it.second);
}
大小=测试图。首先查找(1)->;
大小=测试图。查找(1)->秒;
printf(“调用map.find(1):找到的条目-k:%lu,v:%lu\n”,a,b);
测试映射擦除(1);
printf(“称为map.erase(1)\n”);
if(test_map.find(1)=test_map.end())
printf(“map.find(1)=test_map.end()\n”);
if(test_map.find(2)=test_map.end())
printf(“map.find(2)=test_map.end()\n”);
大小c=测试图。首先查找(1)->;
尺寸d=测试图。查找(1)->秒;
printf(“调用map.find(1):找到的条目-k:%lu,v:%lu\n”,c,d);
printf(“再次迭代映射:\n”);
for(const auto&it:test_map)
{
printf(“找到的条目-k:%lu,v:%lu\n”,it.first,it.second);
}
返回0;
}
输出

./map_test 
map<size_t, size_t> with 2 key-value pairs: (1,2) and (2,1). Iterating over map:
entry found - k: 1, v: 2
entry found - k: 2, v: 1
Called map.find(1): entry found - k: 1, v: 2
Called map.erase(1)
map.find(1) == test_map.end()
Called map.find(1): entry found - k: 1, v: 94380092077776 // k stays, v random
Iterating over map again:
entry found - k: 2, v: 1
/map\u测试
具有两个键值对的映射:(1,2)和(2,1)。在地图上迭代:
找到条目-k:1,v:2
找到条目-k:2,v:1
调用map.find(1):找到条目-k:1,v:2
调用map.erase(1)
map.find(1)=test_map.end()
调用map.find(1):找到条目-k:1,v:9438009207776//k停留,v随机
再次在地图上迭代:
找到条目-k:2,v:1

根据(重点矿山)的文件:

向映射的最后一个元素后面的元素返回迭代器

该元素充当占位符试图访问它会导致未定义的行为

关于:

编译器不需要诊断未定义的行为(尽管诊断了许多简单的情况),编译的程序也不需要做任何有意义的事情

这就是你看到的。行为由实现定义


std::map
的特定情况下,
std::map::find()
返回经过最后一个元素的迭代器,
std::map::end()
返回相同的迭代器;因此,需要对它们进行比较以进行测试

超过最后一个元素的迭代器或
std::map::end()
返回一个有效的迭代器,但它不可取消引用。请参阅:

参考关联容器的规则,除了对已删除元素的迭代器/引用之外,所有迭代器都是有效的


阅读此,以便总结迭代失效(也包括引用相关C++标准的章节)。编译器可以假设您知道自己在做什么,并且永远不会取消引用无效的迭代器,因此,当您取消引用无效的迭代器时,可能会发生奇怪的事情。编译器如此重视我这个程序员,真是太好了。:)这是否与释放malloced空间并随后访问它的行为相同?如果是这样的话,你知道为什么键会坚持原来的值,而这个值不会吗?是的。我不知道你为什么会得到这样的结果,但是分析为什么未定义的行为会以某种方式表现通常是没有用的。谢谢你的快速回复。既然这是在评论中做的,我该如何总结这个问题呢?老实说,我可能应该把我的评论作为一个答案。如果你愿意,你可以自己发布答案并接受。