deque 居然已经实现了 insert 接口

最近有个开发需求,根据server传递来的广告位来展示某条广告。

但最终存储广告的数据结构是deque,里面存储的东西还是对象(stl 基于拷贝语义)。

想了半天,在开头和结尾插入比较方便,在中间插入就有些困难了——因为是双端队列,思维惯性啊!

另外一个问题deque中存储的是对象,这个涉及到覆盖和新的拷贝问题,如果对象很大(这就是现实),那会影响性能。

网上

但是产品需要摆在那边,没办法需要实现啊,只能在可能的情况下,尽量减少拷贝。

于是想到如果插入位置在deque的前半部分,就对deque的前半部分进行操作(pop_front等),如果在deque的后半部分,

就在deque的后半部分(push_back())进行操作。

实现的过程中,有些接口忘了,去cppreference.com 上去查deque的接口,发现deque有insert接口——当时就崩溃了,有木有!!!

http://en.cppreference.com/w/cpp/container/deque/insert

iterator insert( iterator pos, const T& value );

于是直接调用接口就好了,STL的实现比直接造的轮子好!!!!

 

但这个不是结束,为什么deque会提供insert接口,它怎么实现的,是否会避免一些数据的拷贝?带着这个问题,我查看了下4.1.2的源码。

 

template <typename _Tp, typename _Alloc>
    typename deque<_Tp, _Alloc>::iterator
    deque<_Tp, _Alloc>::
    insert(iterator position, const value_type& __x)
    {
      if (position._M_cur == this->_M_impl._M_start._M_cur)
    {
      push_front(__x);
      return this->_M_impl._M_start;
    }
      else if (position._M_cur == this->_M_impl._M_finish._M_cur)
    {
      push_back(__x);
      iterator __tmp = this->_M_impl._M_finish;
      --__tmp;
      return __tmp;
    }
      else
        return _M_insert_aux(position, __x);
    }

 

可以看到这个函数,先判断了pos的位置,如果在前面插入,则调用push_front,如果在末尾插入,则调用push_back。

我们关注的在中间插入,走向了_M_insert_aux函数。

template <typename _Tp, typename _Alloc>
    typename deque<_Tp, _Alloc>::iterator
    deque<_Tp, _Alloc>::
    _M_insert_aux(iterator __pos, const value_type& __x)
    {
      difference_type __index = __pos - this->_M_impl._M_start;
      value_type __x_copy = __x; // XXX copy
      if (static_cast<size_type>(__index) < size() / 2)
    {
      push_front(front());
      iterator __front1 = this->_M_impl._M_start;
      ++__front1;
      iterator __front2 = __front1;
      ++__front2;
      __pos = this->_M_impl._M_start + __index;
      iterator __pos1 = __pos;
      ++__pos1;
      std::copy(__front2, __pos1, __front1);
    }

。。。。。

这个的实现,与我们当时的设想很类似,即看插入的位置与中间元素的关系,如果在前面,则push_front,否则push_back

 

总结1. STL的人很有爱(某人说的),这个接口都提供了,而且实现效率还可以。

2. STL的接口文档需要经常看看,避免造轮子。

 

posted @ 2015-01-17 19:27  westfly  阅读(1345)  评论(0编辑  收藏  举报