换句话说,如果我用完全相同的内容和相同的散列函数填充两个unordered_map
或unordered_set
对象,迭代它们会得到相同的键/值对序列吗?
如果是这样,那么它保持的条件是什么(例如,相同的散列函数,相同的键,不一定相同的值)。
换句话说,如果我用完全相同的内容和相同的散列函数填充两个unordered_map
或unordered_set
对象,迭代它们会得到相同的键/值对序列吗?
如果是这样,那么它保持的条件是什么(例如,相同的散列函数,相同的键,不一定相同的值)。
不。例如,没有要求以任何特定顺序放置具有相同哈希的对象。事实上,一般来说,无序映射不可能做到这一点,因为它可以访问的唯一信息是哈希值。
这种情况下的行为是未定义的。因此,在某些情况下,顺序将是相同的,在其他情况下 - 不同。你无法确定任何事情。您提到的类型被命名为无序并非偶然。将它们作为有序的使用是一种非常非常糟糕且极其危险的风格。
您会发现您的编译器以您希望使用的某种特殊方式运行。但你不能确定。你不能确定!您不知道,是什么条件导致了编译器的这种行为。您永远无法确定编译器版本的任何更改都不会改变您需要的行为。
其他语言中简单禁止的内容,在 C/C++ 中没有指定。但是你也应该把它当作禁止的。
看c-faq关于未定义行为的问题这个概念是所有C/C++通用的
那么首先我将引用MSDN:
受控序列中元素的实际顺序取决于散列函数、比较函数、插入顺序、最大负载因子和当前桶数。您通常无法预测受控序列中元素的顺序。但是,您始终可以确信,任何具有等价顺序的元素子集在受控序列中都是相邻的。
上面的引用对于unordered_map
and是相同的,unordered_set
并且顾名思义,序列是未指定的,但是,他们确实提到等效键是相邻的。
如果您需要有保证的订购,这不是适合您的数据结构。实际上,如果您主要进行迭代,unordered_map/set
那么数据结构也不适合您。
对于迭代,astd::map
将被证明是更好的数据结构,因为从一个节点到下一个节点的 gonig 在算法上不太复杂。并且对象的迭代顺序std::map
由规范保证(实际上是结构本身的定义属性)。(显然,这一切都假设您使用的是相同的比较运算符)。不涉及散列std::map
。
我只想说,听起来你在这里吠错了树。unordered_map
通常应该用于诸如 O(1) 查找之类的好处,而不是用于存储对象列表然后对其进行迭代。如果您试图获得确定的迭代顺序,则绝对不应该使用它。