C++ 分配时无序地图更改的顺序

C++ 分配时无序地图更改的顺序,c++,dictionary,unordered-map,C++,Dictionary,Unordered Map,我对这种行为很好奇。我发现分配一个无序映射会改变无序映射的内部顺序,而不会进行任何插入/删除: unordered_map<int, string> m1; unordered_map<int, string> m2; unordered_map<int, string> m3; m1[2] = "john"; m1[4] = "sarah"; m1[1] = "mark"; m2 = m1; m3 = m2; for(auto it = m1.begi

我对这种行为很好奇。我发现分配一个
无序映射
会改变无序映射的内部顺序,而不会进行任何插入/删除:

unordered_map<int, string> m1;
unordered_map<int, string> m2;
unordered_map<int, string> m3;

m1[2] = "john";
m1[4] = "sarah";
m1[1] = "mark";

m2 = m1;
m3 = m2;

for(auto it = m1.begin(); it != m1.end(); ++it) {
    cout << it->second << " ";
}
cout << endl;
for(auto it = m2.begin(); it != m2.end(); ++it) {
    cout << it->second << " ";
}
cout << endl;
for(auto it = m3.begin(); it != m3.end(); ++it) {
    cout << it->second << " ";
}
cout << endl;
我知道,
无序映射
上没有任何特定的顺序,因为内部是一个哈希表,因此元素插入可以在任何地方结束,而重新哈希将混合所有元素

然而,这里的顺序是在分配任务之后改变的。我希望顺序是一样的,因为我认为它只会复制底层存储

我想到的第一个解释是,
unordered_-map
可能是利用拷贝将新映射重新散列为更优化的排列。但是,我尝试在m2的新地图(m3)上重复一个赋值,m2的顺序在m3中没有保留

为什么分配地图会改变顺序


我的编译器是Apple LLVM版本8.1.0(clang-802.0.42)

,因为这显然是特定于实现的(毕竟是一个无序的映射),所以我要做一个有根据的推测


如果
mark
john
具有相同的哈希和冲突,并且实现使用了链接,那么我们可以解释这一点。如果链接实现在前端插入新项目(即使对于单个链接列表也是固定时间),则每次分配容器时,链接项目顺序都将被交换。

这是以下内容的实现细节:

如果我们假设您使用的是C++11或更高版本,那么这基本上是通过清除旧的哈希表,然后将
\uu
的元素插入到这个向量中来实现的

这意味着当你这样做时:

m2 = m1;
它大致相当于以下代码:

m2.clear();
m2.max_load_factor(m1.max_load_factor());
m2.insert(m1.begin(), m1.end());

使用时不会发生这种情况,因为其
操作符=
的实现只是
=默认值
(请参阅libstdc++)

我喜欢这样的部分,即您认识到无序映射没有内部顺序。。。。然后我仍然想知道为什么订单没有consistent@CoryKramer不过,这是个好问题。问题是为什么备份存储没有按原样复制;为什么要重新安排?@CoryKramer是的,我知道这是标准的答案。但OP的问题是为什么它会以这种方式实施。即使这是特定于实现的细节,这也是一个好问题(对于SO来说可能不是一个好问题,但这是一个好问题)您使用的是什么实现。给出“预期的”results@GonzaloSolera如果您添加一个
m4
add assign
m3
到它,那么
m4
看起来像
m2
?在wandbox上尝试它,我的“等效代码”不是很等效:。这可能只是一个不同版本的libc++,或者是一个不同的标准库。我觉得
mark
john
不太可能有相同的散列,如果是这样的话,问题应该通过使用不同的字符串来解决,但情况似乎并非如此(例如)。当然,不同的字符串也可能会发生冲突,但要找到不冲突的字符串应该不难。
m2 = m1;
m2.clear();
m2.max_load_factor(m1.max_load_factor());
m2.insert(m1.begin(), m1.end());