迭代通过std :: map的顺序是否已知(并由标准保证)?

时间:2011-10-04 13:35:23

标签: c++ dictionary stl standards

我的意思是 - 我们知道std::map的元素是根据键排序的。所以,让我们说键是整数。如果我使用std::map::begin()std::map::end()迭代到for,标准是否保证我会通过带有键的元素进行迭代,按升序排序?


示例:

std::map<int, int> map_;
map_[1] = 2;
map_[2] = 3;
map_[3] = 4;
for( std::map<int, int>::iterator iter = map_.begin();
     iter != map_.end();
     ++iter )
{
    std::cout << iter->second;
}

这是保证打印234还是实现定义?


现实生活中的原因:我有std::mapint个键。在非常罕见的情况下,我想迭代所有元素,使用key,而不是具体的int值。是的,听起来std::vector会是更好的选择,但请注意我的“非常罕见的情况”。


编辑:我知道,std::map的元素已排序..无需指出(对于此处的大多数答案)。我甚至在我的问题中写了这篇文章 我在迭代容器时询问迭代器和顺序。谢谢@Kerrek SB的回答。

6 个答案:

答案 0 :(得分:158)

是的,这是有保证的。此外,*begin()为您提供最小且*rbegin()最大元素(由比较运算符确定)和两个键值ab,其表达式为{{1}是真的被认为是平等的。默认比较函数为!compare(a,b) && !compare(b,a)

排序不是一个幸运的奖励功能,而是它是数据结构的一个基本方面,因为排序用于确定两个键何时相同(通过上述规则)并执行有效查找(本质上是一个二元搜索,它具有元素数量的对数复杂度。)

答案 1 :(得分:40)

这是由C ++标准中的关联容器要求保证的。例如。参见C ++ 11中的23.2.4 / 10:

The fundamental property of iterators of associative containers is that they
iterate through the containers in the non-descending order of keys where
non-descending is defined by the comparison that was used to construct them.
For any two dereferenceable iterators i and j such that distance from i to j is
positive,
  value_comp(*j, *i) == false

和23.2.4 / 11

For associative containers with unique keys the stronger condition holds,
  value_comp(*i, *j) != false.

答案 2 :(得分:26)

我认为数据结构存在混淆。

在大多数语言中,map只是一个AssociativeContainer:它将一个键映射到一个值。在“较新”的语言中,这通常使用哈希映射来实现,因此不保证订单。

然而,在C ++中,情况并非如此:

  • std::map已排序关联容器
  • std::unordered_map是在C ++ 11中引入的基于哈希表的关联容器

因此,为了澄清订购的保证。

在C ++ 03中:

    保证根据密钥(以及提供的标准)订购
  • std::setstd::multisetstd::mapstd::multimap
  • std::multisetstd::multimap中,标准不对等效元素(即比较相等的元素)强加任何订单保证。

在C ++ 11中:

    保证根据密钥(以及提供的标准)订购
  • std::setstd::multisetstd::mapstd::multimap
  • std::multisetstd::multimap中,标准强加等效元素(比较相等的元素)按照其插入顺序排序(首先插入)
  • std::unordered_*容器,顾名思义,未订购。最值得注意的是,当容器被修改时(插入/删除时),元素的顺序可能会

当标准表示元素以某种方式排序时,意味着:

  • 迭代时,您会看到定义顺序的元素
  • 反向迭代时,您会看到相反顺序的元素

我希望这可以解决任何困惑。

答案 3 :(得分:4)

  

这是否可以保证打印234或它的实现定义?

是的,std::map是一个已排序的容器,由Key按提供的Comparator排序。所以它是有保障的。

  

我想用密钥迭代所有元素,大于具体的int值。

这当然是可能的。

答案 4 :(得分:3)

是...... std::map中的元素具有严格的弱排序,这意味着元素将由一个集合组成(即,不会重复“等于”的键),通过测试任意两个键A和B来确定相等性,即如果键A不小于键B,且B不小于A,则键A等于键B.

话虽如此,如果该类型的弱排序不明确,则无法正确排序std::map的元素(在您的情况下,您使用整数作为键类型,而不是问题)。您必须能够定义一个操作,该操作定义您用于std::map中的键的类型的总订单,否则您将只对您的元素或poset有一个部分订单,其中包含A的属性可能无法与B.相比较。在这种情况下通常会发生的是您将能够插入键/值对,但如果您遍历整个地图,最终可能会出现重复的键/值对,和/当您尝试在地图中执行std::map::find()特定键/值对时,检测“丢失”键/值对。

答案 5 :(得分:-2)

begin()可能会给出最小的元素。但这取决于实现。它在C ++标准中指定吗?如果没有,那么做这个假设是危险的。