关于map与unorderedmap

  今天在看effective modernc++的时候注意到了一个细节,在用c++11新标准遍历map时的参数的类型的key要为const,否则访问的是一个局部对象,这个我一直都没有注意到,现在复习一下:

  查阅http://www.cplusplus.com/reference/map/map/?kw=map

  注意到map声明为

template < class Key,                                     // map::key_type
           class T,                                       // map::mapped_type
           class Compare = less<Key>,                     // map::key_compare
           class Alloc = allocator<pair<const Key,T> >    // map::allocator_type
           > class map;

  unordermap也是一样。key有const修饰。

  测试以下代码

int main() {
    map<std::string, int> m;
    m["1"] = 1;
    for (const std::pair<std::string, int>& p : m)
    {
        cout << "addr in local:" << &p << "   addr in object:" << &(*m.begin())<<endl;
    }
    for (const auto& p : m)
    {
        cout << "addr in local:" << &p << "   addr in object:" << &(*m.begin())<<endl;
    }
    system("pause");
    return 0;
}

  结果为:

addr in local:00000031A98FF468 addr in object:000001F6028059B0
addr in local:000001F6028059B0 addr in object:000001F6028059B0

  可以看到第一次以非const访问时的地址的不同。其原因是因为遍历放回的类型为std::pair<const std::string,int>,而循环中的声明的类型为std::pair<std::string,int>,编译器能够为上述类型进行隐式的转化:先拷贝一个局部变量,然后for中的p就引用到这个临时变量上。

  review一下的底层原理:

  map底层是一个平衡二叉树,红黑树,插入与删除时间复杂度为O(lgn)。

  unorderedmap则是一个链表,使用开放定址法的链式hash策略。插入与删除最好是常量,最坏是O(n)。rehash时最好是O(n),最坏是O(n^2)

 

posted @ 2019-11-07 16:27  manch1n  阅读(252)  评论(0编辑  收藏  举报