关联容器中的end()迭代器 这个代码是否适用于所有符合标准的C++编译器(它与G++一起工作)?为什么(如果可能,请提供c++11参考)?一般来说,std::无序的_映射和关联容器如何 std::map<std::string, std::string> map; std::map<std::string, std::string>::iterator i(map.end()); map.insert({"bla", ""}); map.insert({"hah", ""}); assert(map.end() == i); std::map; std::map::迭代器i(map.end()); 插入({bla',“”}); map.insert({hah',“”}); 断言(map.end()==i);

关联容器中的end()迭代器 这个代码是否适用于所有符合标准的C++编译器(它与G++一起工作)?为什么(如果可能,请提供c++11参考)?一般来说,std::无序的_映射和关联容器如何 std::map<std::string, std::string> map; std::map<std::string, std::string>::iterator i(map.end()); map.insert({"bla", ""}); map.insert({"hah", ""}); assert(map.end() == i); std::map; std::map::迭代器i(map.end()); 插入({bla',“”}); map.insert({hah',“”}); 断言(map.end()==i);,c++,stl,C++,Stl,代码在此处使用扩展的Initializer列表: map.insert({"bla", ""}); // the {"bla", ""} 这是C++ 11的特性,因此在非C++ 11编译器上不能工作。 编写编译器: GCC 4.4.1及所有更高版本 不工作: 数字火星C++ Borland C++(不是主流,但仍然检查) Visual C++ 显然,大多数编译器不支持C++ 11 从C++ 03标准部分23.1.2关联容器[LIB,关联,ReqMTS],点8状态: 插入成员不得影响

代码在此处使用扩展的Initializer列表:

map.insert({"bla", ""}); // the {"bla", ""}

这是C++ 11的特性,因此在非C++ 11编译器上不能工作。 编写编译器:

  • GCC 4.4.1及所有更高版本
不工作:

  • 数字火星C++
  • Borland C++(不是主流,但仍然检查)
  • Visual C++
  • 显然,大多数编译器不支持C++ 11

从C++ 03标准部分23.1.2关联容器[LIB,关联,ReqMTS],点8状态:

插入成员不得影响迭代器和容器引用的有效性,擦除成员应 仅使迭代器和对已删除元素的引用无效

根据C++11标准第23.2.4节关联容器[Associative.reqmts],第9点规定:

insert成员不得影响迭代器和容器引用的有效性,以及erase 成员应仅使迭代器和对已删除元素的引用无效

基于此,发布代码中的
assert()
将为
true

编辑:

对于未排序的容器,这些引号不是正确的:请参见中的答案。

对于映射,是的——实际上除了删除引用的对象之外,什么都不会使映射中的迭代器失效

对于无序的_映射,在实践中,对于这种特定情况可能是肯定的-
end
迭代器通常与其他迭代器稍有不同,因此它可能不包含任何实际地址或类似的内容-,它只是一个特殊的哨兵值,其他迭代器在遍历整个容器后将与之进行比较


但这并不能保证。特别是,你的插入可能会导致再洗牙,[编辑:在这里,我或多或少地假设您的两个插入是作为一些任意数量的插入的占位符。您可以确定是否会对特定的负载因子、插入数量等进行重新哈希,但您通常不想这样做——这取决于它会导致脆弱的代码],重新哈希会使迭代器无效(§23.2.5/8)。尽管(如上所述)由
end()
返回的迭代器通常是“特殊”的,但标准并不要求这样做,因此在插入之后,您以前从
end
获得的结果可能无效,因此实际上不需要任何关于迭代器的信息(包括与任何特定内容进行比较).

您似乎在寻找有关内部失效的标准引用:

对于
set、multiset、map和multimap

insert成员不得影响迭代器和容器引用的有效性,以及erase 成员应仅使迭代器和对已删除元素的引用无效

对于
unordered\u集、unordered\u映射、unordered\u multiset和unordered\u multimap

如果(N+N)
因此,对于
map
插入不会使
end
迭代器无效,但是对于
unordered\u map
而言,如果添加到现有元素数的元素数超过
bucket\u count*max\u load\u factor
end
迭代器指示无法通过cont进一步迭代因此,当新元素插入容器中时,应预期会发生变化


映射通常作为二叉树实现,并且可能使用特殊值(例如NULL)表示进一步的迭代是不可能的。但这是底层实现的结果,与指定的行为无关。

的确,但我要求从c++11标准中获得参考,但无论如何,如果您愿意,您可以用c++03的方式进行插入。结束()迭代器在插入时保持不变?请参见assert()?如果代码未编译,您无法检查它是否工作。@user1095108抱歉,您的问题没有正确理解,请稍等,我将尝试查找引用。我在C++11标准23.2.4中发现了类似的语句:insert和emplace成员不应影响迭代器的有效性和对容器的引用,以及erase members只能使迭代器和对已删除元素的引用无效。谢谢。@user1095108,刚刚将其添加到我的答案中。@user1095108这不适用于无序映射,请参见下面的答案。如果标准规定
不应影响迭代器的有效性
,我将假定它包括
end()返回的迭代器
,这不是真的吗?是的,
end
返回的是一个迭代器,因此如果您的操作没有使迭代器无效,它将保持有效。许多不错的答案,但我检查了这个答案,因为它最接近我遇到的问题。我使用end()迭代器作为“这是一个无效迭代器”指示符(类似于“NULL”迭代器)这可能会导致可避免的错误,因为如果使用无序的关联容器,存储的end()迭代器不能保证与它最初来自的容器的end()迭代器进行比较。