关联容器中的end()迭代器

时间:2012-03-27 09:13:39

标签: c++ stl

此代码是否适用于所有符合标准的C ++编译器(它适用于g ++)?为什么(请尽可能提供c ++ 11参考)?一般来说std :: unordered_map和关联容器怎么样?

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);

5 个答案:

答案 0 :(得分:2)

对于map,yes - 除了删除引用的对象之外几乎没有任何东西可以使映射中的迭代器无效。

有关unordered_map,在实践中,也许是这种特定的情况 - end迭代器往往是从其他迭代器有点不同,所以它可能不包含任何实际的地址或类似的东西 - 它只是一个在迭代整个容器之后,其他迭代器将比较的特殊sentinel值。

但这并不能保证。具体来说,你的插入可能导致重新散列,[编辑:这里我或多或少地假设你的两个插入是作为一些任意数量的插入的占位符。你可以找出是否换汤不换药发生特定负载因数,插入,数量等,但一般不希望 - 这取决于它会导致脆弱的代码]和换汤不换药无效迭代器(§23.2.5/ 8)。虽然(如上所述)end()返回的迭代器通常是“特殊的”,但标准并不要求,因此在插入之后,您之前从end获得的内容可能无效,因此实际上没有必要(包括比较等于任何东西)。

答案 1 :(得分:2)

您似乎正在寻找关于交互无效的标准的引用:

set, multiset, map and multimap

  

插入成员不应影响迭代器的有效性和对容器的引用以及擦除   成员只能使迭代器和对已擦除元素的引用无效。

unordered_set, unordered_map, unordered_multiset, and unordered_multimap

  

如果(N + n),插入成员不应影响迭代器的有效性。 z * B,其中N是数字   在插入操作之前容器中的元素,n是插入的元素的数量,B是   容器的桶数,z是容器的最大负载系数。

因此,对于map插入不会使end迭代器无效,但是,对于unordered_map,如果添加到现有元素数的元素数超过bucket_count * max_load_factor }。

答案 2 :(得分:1)

从C ++ 03标准部分 23.1.2关联容器[lib.associative.reqmts] ,第8点指出:

  

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

从C ++ 11标准部分 23.2.4关联容器[associative.reqmts] ,第9点指出:

  

插入成员不应影响迭代器的有效性和对容器的引用以及擦除   成员只能使迭代器和对已擦除元素的引用无效。

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

编辑:

这些引号不适用于unordered容器:请参阅Jesse的回答。

答案 3 :(得分:0)

代码在此处使用扩展的初始化列表:

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

这是一个C ++ 11特性,因此不适用于非C ++ 11编译器。

使用编译器:

  • GCC 4.4.1及所有更高版本

不工作:

  • Digital Mars C ++
  • Borland C ++(不完全是主流,但仍然检查过)
  • Visual C ++
  • 显然大多数不支持C ++ 11的编译器

答案 4 :(得分:0)

end迭代器表示无法进一步遍历包含,因此应该在将新元素插入容器时进行更改。

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