如果有insert / remove / rehash操作,unordered_map copy / release是否包含对象?

时间:2011-12-29 05:24:02

标签: c++ boost stl

我想在unordered_map中存储小对象,只是想知道是否可以复制/释放包含的对象,如果有任何插入/删除/重新执行操作?我认为unordered_map使用链接列表来存储键/值对,它不需要复制/释放像vector这样的对象用于内存重新分配。

2 个答案:

答案 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。