C++学习 - Map的了解

Map

map的特性是,所有键值会自动被排序。所有元素都是pair类型,同时拥有实体值(value)和键值(key)。pair的第一个元素被看做为键值,第二个看作为实值。

同set,map不允许两个元素有相同的键值。又因为键值的自动排列特性,所以在键类型上必须有定义的严格弱排序。所谓的严格弱排序可以理解为在键值类型上的小于关系。

所以假如不存在两个键值的小于关系,则容器会视为相同的键。

map属于关联容器

map的底层是用红黑树实现的

map迭代器

map的迭代器不能改变元素的键值,但是能改变实值。因为键值是自动排列的,改变键值的话,会影响map的组织,所以map iterator不是一种constant iterator, 也不是一种 mutable iterator.

map的迭代器进行解引用将产生pair类型对象。

迭代器失效

map拥有和list相同的某些性质:当客户端对它进行元素的新增(insert)和删除的时候,在操作之前和操作之后都依然有效,当然除了被删除的那个元素。

我们先看一下我截取的部分的map的源码。

//map source code from map.h
 // modifiers:
      std::pair<iterator, bool>
      insert(const value_type& __x)
      {
    typedef typename _Base::iterator _Base_iterator;
    std::pair<_Base_iterator, bool> __res = _Base::insert(__x);
    return std::pair<iterator, bool>(iterator(__res.first, this),
                     __res.second);
      }

      iterator
      insert(iterator __position, const value_type& __x)
      {
    __glibcxx_check_insert(__position);
    return iterator(_Base::insert(__position.base(), __x), this);
      }

      template<typename _InputIterator>
        void
        insert(_InputIterator __first, _InputIterator __last)
        {
      __glibcxx_check_valid_range(__first, __last);
      _Base::insert(__first, __last);
    }

      void
      erase(iterator __position)
      {
    __glibcxx_check_erase(__position);
    __position._M_invalidate();
    _Base::erase(__position.base());
      }

      size_type
      erase(const key_type& __x)
      {
    iterator __victim = find(__x);
    if (__victim == end())
      return 0;
    else
    {
      __victim._M_invalidate();
      _Base::erase(__victim.base());
      return 1;
    }
      }

      void
      erase(iterator __first, iterator __last)
      {
    // _GLIBCXX_RESOLVE_LIB_DEFECTS
    // 151. can't currently clear() empty container
    __glibcxx_check_erase_range(__first, __last);
    while (__first != __last)
      this->erase(__first++);
      }

以上部分代码不需要看起来很难,其实就是一些函数声明和重载。

我们可以看到在使用insert的插入元素情况,除了使用开始指针和结束指针的方法来初始化,其他的都会返回新的需要的元素,利用迭代器插入的时候,会返回新元素的迭代器的位置。

所以我们在使用的时候:

iter = map.insert(iter, value);

这样子就不会出现迭代器失效了。

但是erase就不行了,因为只有序列容器的erase返回的才是删除后下一个元素的iterator. 而map这种关联容器,从源码中就可以看到返回值是void.

所以我们在删除操作的时候:

map.erase(iter++);

这样子才可以。

map初始化

  • map<k, v> m;创建一个m的空map对象。
  • map<k, v> m(m2);创建一个m2的副本,k,v必须类型相同
  • map<k, v> m(b, e);创建迭代器b和e标记范围内的所有元素的副本。这元素类型必须能转换为pair<const k, v>

map插入元素

定义一个map: map <string, int> word;
1. 比较简单,直接下标:word["alps"] = 1;
2. 使用insert: word.insert(make_pair("alps", 1));就可以了。
3. 或者typedef:typedef map<string, int>::value_type valType; word.insert(valType("alps", 1));

大致如上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值