【发布时间】:2016-07-16 21:42:31
【问题描述】:
一本书提到std::unordered_multimap:
元素的顺序未定义。唯一的保证是 由于使用了多重集而可能出现的重复项被分组 按照插入的顺序放在一起。
但从下面示例的输出中,我们可以看到打印顺序与它们的插入相反。
#include <string>
#include <unordered_map>
int main()
{
std::unordered_multimap<int, std::string> um;
um.insert( {1,"hello1.1"} );
um.insert( {1,"hello1.2"} );
um.insert( {1,"hello1.3"} );
for (auto &a: um){
cout << a.first << '\t' << a.second << endl;
}
}
编译和运行时会产生此输出 (g++ 5.4.0):
1 hello1.3
1 hello1.2
1 hello1.1
更新: unordered_multiset 有同样的问题:
auto cmp = [](const pair<int,string> &p1, const pair<int,string> &p2)
{return p1.first == p2.first;};
auto hs = [](const pair<int,string> &p1){return std::hash<int>()(p1.first);};
unordered_multiset<pair<int, string>, decltype(hs), decltype(cmp)> us(0, hs, cmp);
us.insert({1,"hello1.1"});
us.insert({1,"hello1.2"});
us.insert({1,"hello1.3"});
for(auto &a:us){
cout<<a.first<<"\t"<<a.second<<endl;
}
输出:
1 hello1.3
1 hello1.2
1 hello1.1
【问题讨论】:
-
The order of the elements is undefined.我想你需要明白标准在说“未定义”时的含义:任何事情都可能发生,但发生什么并不重要,任何人都不应该依赖什么可能发生在星期二,风向东吹。实现可以根据需要定义一个顺序 - 可能是不故意拜占庭的副作用 - 但标准没有。就这样。话虽如此,如果您要插入更多元素,您可能会发现“可预测”的顺序开始崩溃。但是,这根本不重要。这是unordered_map。 -
@underscore_d: 不,这是一个
unordered_multimap,其中 C++14 November 2014 草案(至少)要求“具有等效键的元素在迭代顺序中彼此相邻容器”和“重新散列保留等效元素的相对顺序”(23.2.5)。我找不到任何关于根据插入顺序定义的相对顺序的信息,但值得了解。 -
@RyanO'Hara 感谢您提供信息。我没有完全处理,因为第一行缺少
multi。现在我们需要知道哪本书是这么说的,而不是说它会比标准更可靠! -
@underscore_d 该语句来自 C++ 标准库 A 教程和参考第 6.2 章容器,在第 183 页的开头: 现在,如果我们打印所有元素,则顺序可能会有所不同,因为顺序未定义.唯一的保证是,由于使用了多重集而可能出现的重复项按照它们的插入顺序组合在一起。
-
@camino 感谢您的引用和额外报价。我认为它的说法没有任何意义。 “顺序未定义”与“按插入顺序组合在一起”直接冲突。它们只是按未定义(尽管通常不变)的顺序组合在一起。
标签: c++ c++11 c++-standard-library unordered-multimap