我想在unordered_map中存储小对象,只是想知道是否可以复制/释放包含的对象,如果有任何插入/删除/重新执行操作?我认为unordered_map使用链接列表来存储键/值对,它不需要复制/释放像vector这样的对象用于内存重新分配。
答案 0 :(得分:10)
C ++ 11标准:§23.2.5/ 8
无序关联容器的元素被组织到存储桶中。具有相同哈希码的密钥出现在同一个存储桶中。当元素添加到无序关联容器时,桶的数量会自动增加,因此每个桶的平均元素数量保持在一个边界之下。 重新散列使迭代器无效,元素之间的顺序更改以及更改哪些存储桶元素,但不会使指针或对元素的引用无效。对于unordered_multiset和unordered_multimap,rehashing保留了等效元素的相对顺序。
简称unordered_map
,
如果是插入/删除操作,
答案 1 :(得分:-1)
我使用此代码进行了测试:
#include <iostream>
#include <unordered_set>
#include <unordered_map>
struct A
{
static int copies;
A(int a): a(a){}
A(A const& pA){std::cout << "A copy" << std::endl; ++copies; a = pA.a;}
A& operator=(A const& pA){std::cout << "= operator" << std::endl; a = pA.a; ++copies; return *this;}
int a;
bool operator==(A const& pA)const{return pA.a == a;}
bool operator!=(A const& pA)const{return pA.a != a;}
bool operator>(A const& pA)const{return pA.a > a;}
bool operator<(A const& pA)const{return pA.a < a;}
};
int A::copies = 0;
namespace std{
template<>
class hash<A>
{
public:
size_t operator()(A const& pA) const
{
return pA.a;
}
};
}
int main()
{
std::unordered_map<A, A> map;
std::unordered_set<A> set;
for(int i=0; i<1000000; ++i)
{
set.insert(A(i));
map.insert(std::pair<A, A>(A(i), A(i)));
}
std::cout << A::copies << std::endl;
return 0;
}
set的拷贝构造函数被称为1毫升 - 这意味着每个对象只被复制一次(进入集合)。对于地图复制构造函数被称为4毫升次 - 宠物对象的2倍(注意每个插入的地图需要2个A对象)。此外,当我运行测试时,我只插入一个对象(对于i&lt; 1)然后复制construcotr被调用一次为set和4次fot map。
结论: 似乎reshash和插入对象不会在unordered_set和unordered_map中重新分配对象。我认为这是真的,因为我不相信这么多插入甚至没有一次重复。复制构造函数被调用一次为set(将对象复制到一个集合节点) - 显而易见。为什么然后复制construcotr被调用4次为每个地图插入调用? Map键是A对象,值也是A对象。创建对象然后复制到std :: pair(前2个副本),然后将对复制到地图中(另外2个副本) - 我认为它是如何工作的。
所以看起来无序的map和set中的对象永远不会被重新分配,因此指针和引用保持有效,但迭代器可能不会 - @Alok保存答案。我做了这个测试,因为我想知道当rehash发生时键是否重新分配。 @Alok Save写了关于元素但没有关于键的信息(或者我没有正确理解他的答案,元素意味着价值和关键)。
问题: 标准是否说明关键的任何内容(如果它们不被视为元素)?
PS: 对于测试,我使用g ++ 4.8。