STL源码剖析(八)序列式容器之deque设计

deque设计

deque除了维护一个指向map的指针外,还维护start,finish两个迭代器,分别指向缓冲区的首尾位置,首位置为缓冲区第一个元素,尾位置为最后一个元素的下一位置即尾后位置。
同时必须记住目前map大小,当map提供的节点不足时,必须重新配置一块更大的map。

namespace std _GLIBCXX_VISIBILITY(default)
{
  template<typename _Tp, typename _Alloc>
    class _Deque_base //deque基类
    {
    protected:
      typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
		rebind<_Tp>::other _Tp_alloc_type; //声明内存分配器_Alloc<_Tp>别名
      typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type>	 _Alloc_traits; //内存分配器_Alloc<_Tp>属性提取

      typedef typename _Alloc_traits::pointer		_Ptr; //内存分配器属性中的指针类型
      typedef typename _Alloc_traits::const_pointer	_Ptr_const;
      typedef typename _Alloc_traits::template rebind<_Ptr>::other
		_Map_alloc_type; //声明元素指针的内存分配器_Alloc<_Ptr>别名,_Ptr为_Tp*
      typedef __gnu_cxx::__alloc_traits<_Map_alloc_type> _Map_alloc_traits; //元素指针的内存分配器_Alloc<_Ptr>属性提取

    public:
      typedef _Alloc		  allocator_type; //内存分配器
      typedef typename _Alloc_traits::size_type size_type;

      typedef _Deque_iterator<_Tp, _Tp&, _Ptr>	  iterator; //声明迭代器
      typedef _Deque_iterator<_Tp, const _Tp&, _Ptr_const>   const_iterator;
      //以下省略所有构造函数和析构函数

    protected:
      typedef typename iterator::_Map_pointer _Map_pointer; //声明指向元素的指针的指针,_Tp**

      struct _Deque_impl //deque内存分配器封装
      : public _Tp_alloc_type //继承自_Alloc<_Tp>
      {
		_Map_pointer _M_map; //指向连续空间map,其内的每个元素都是指针(节点),指向一块缓冲区
		size_t _M_map_size; //map内可容纳多少指针,即有多少个缓冲区
		iterator _M_start; //缓冲区首位置,指向首元素
		iterator _M_finish; //缓冲区尾位置,指向尾后元素
        //以下省略所有构造函数

		void _M_swap_data(_Deque_impl& __x) _GLIBCXX_NOEXCEPT //交换操作
		{
		  using std::swap; //使用std::swap,交换_Deque_impl中所有成员
		  swap(this->_M_start, __x._M_start);
		  swap(this->_M_finish, __x._M_finish);
		  swap(this->_M_map, __x._M_map);
		  swap(this->_M_map_size, __x._M_map_size);
		}
      }; //_Deque_impl

      _Ptr //返回指针
      _M_allocate_node() //配置内存
      {
		typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Traits; //内存分配器_Alloc<_Tp>属性提取
		return _Traits::allocate(_M_impl, __deque_buf_size(sizeof(_Tp))); //allocate配置内存
      }

      void
      _M_deallocate_node(_Ptr __p) _GLIBCXX_NOEXCEPT //释放内存
      {
		typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Traits;//内存分配器_Alloc<_Tp>属性提取
		_Traits::deallocate(_M_impl, __p, __deque_buf_size(sizeof(_Tp))); //deallocate释放内存
      }

      _Map_pointer //配置缓冲区内存
      _M_allocate_map(size_t __n)
      {
		_Map_alloc_type __map_alloc = _M_get_map_allocator(); //内存分配类型
		return _Map_alloc_traits::allocate(__map_alloc, __n); //allocate配置内存并返回
      }

      void //释放缓冲区内存
      _M_deallocate_map(_Map_pointer __p, size_t __n) _GLIBCXX_NOEXCEPT
      {
		_Map_alloc_type __map_alloc = _M_get_map_allocator(); //内存类型
		_Map_alloc_traits::deallocate(__map_alloc, __p, __n); //deallocate释放内存
      }

    protected:
      void _M_initialize_map(size_t);
      void _M_create_nodes(_Map_pointer __nstart, _Map_pointer __nfinish);
      void _M_destroy_nodes(_Map_pointer __nstart,
			    _Map_pointer __nfinish) _GLIBCXX_NOEXCEPT;
      enum { _S_initial_map_size = 8 }; //枚举值,map管理的节点数最少为8

      _Deque_impl _M_impl;

    private:
      _Deque_impl
      _M_move_impl()
      {
		if (!_M_impl._M_map)
		  return std::move(_M_impl);
	
		_Tp_alloc_type __alloc{_M_get_Tp_allocator()};
		_Tp_alloc_type __sink __attribute((__unused__)) {std::move(__alloc)};
		_Deque_base __empty{__alloc};
		__empty._M_initialize_map(0);
		_Deque_impl __ret{std::move(_M_get_Tp_allocator())};
		_M_impl._M_swap_data(__ret);
		_M_impl._M_swap_data(__empty._M_impl);
		return __ret;
      }
    }; //_Deque_base

  template<typename _Tp, typename _Alloc>
    _Deque_base<_Tp, _Alloc>::
    ~_Deque_base() _GLIBCXX_NOEXCEPT //析构函数
    {
      if (this->_M_impl._M_map)
		{
		  _M_destroy_nodes(this->_M_impl._M_start._M_node,
				   this->_M_impl._M_finish._M_node + 1);
		  _M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size);
		}
    }

  template<typename _Tp, typename _Alloc>
    void
    _Deque_base<_Tp, _Alloc>:: //设定map的size
    _M_initialize_map(size_t __num_elements)
    {
      const size_t __num_nodes = (__num_elements/ __deque_buf_size(sizeof(_Tp))
				  + 1); //map所需要缓冲区数=(元素个数/缓冲区可容纳元素)+1,刚好整除时,会多配一个

      this->_M_impl._M_map_size = std::max((size_t) _S_initial_map_size, //一个map管理的缓冲区
					   size_t(__num_nodes + 2)); //最少8个,最多所需缓冲区数+2,前后各预留一个,扩充时可用
      this->_M_impl._M_map = _M_allocate_map(this->_M_impl._M_map_size);

      _Map_pointer __nstart = (this->_M_impl._M_map //__nstart指向map中间区段,使头尾都可扩充
			       + (this->_M_impl._M_map_size - __num_nodes) / 2); //每个节点对应一个缓冲区
      _Map_pointer __nfinish = __nstart + __num_nodes; //__nfinish指向map中间区段

      __try
	{ _M_create_nodes(__nstart, __nfinish); } //为map现有节点配置缓冲区,所有缓冲区即是deque可用空间
      __catch(...) //如若没有全部成功,则一个不留
	{
	  _M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size);
	  this->_M_impl._M_map = _Map_pointer();
	  this->_M_impl._M_map_size = 0;
	  __throw_exception_again;
	}
      //为迭代器_M_start、_M_finish设定正确内容
      this->_M_impl._M_start._M_set_node(__nstart);
      this->_M_impl._M_finish._M_set_node(__nfinish - 1);
      this->_M_impl._M_start._M_cur = _M_impl._M_start._M_first;
      this->_M_impl._M_finish._M_cur = (this->_M_impl._M_finish._M_first
					+ __num_elements
					% __deque_buf_size(sizeof(_Tp)));
    }

  template<typename _Tp, typename _Alloc>
    void
    _Deque_base<_Tp, _Alloc>::
    _M_create_nodes(_Map_pointer __nstart, _Map_pointer __nfinish)
    {
	      _Map_pointer __cur;
	      __try
		{
		  for (__cur = __nstart; __cur < __nfinish; ++__cur)
		    *__cur = this->_M_allocate_node();
		}
	      __catch(...)
		{
		  _M_destroy_nodes(__nstart, __cur);
		  __throw_exception_again;
		}
    }

  template<typename _Tp, typename _Alloc>
    void
    _Deque_base<_Tp, _Alloc>::
    _M_destroy_nodes(_Map_pointer __nstart,
		     _Map_pointer __nfinish) _GLIBCXX_NOEXCEPT
    {
      for (_Map_pointer __n = __nstart; __n < __nfinish; ++__n)
		_M_deallocate_node(*__n);
    }

  template<typename _Tp, typename _Alloc = std::allocator<_Tp> > //容器deque
    class deque : protected _Deque_base<_Tp, _Alloc>
    {
      static_assert(is_same<typename remove_cv<_Tp>::type, _Tp>::value,
	  "std::deque must have a non-const, non-volatile value_type");

      typedef _Deque_base<_Tp, _Alloc>			_Base; //基类
      typedef typename _Base::_Tp_alloc_type		_Tp_alloc_type; //基类内存分配器_Alloc<_Tp>
      typedef typename _Base::_Alloc_traits		_Alloc_traits; //基类内存分配器的属性
      typedef typename _Base::_Map_pointer		_Map_pointer; //基类指向元素指针的指针,_Tp**

    public: //类型别名
      typedef _Tp					value_type; //元素类型
      typedef typename _Alloc_traits::pointer		pointer; //指针类型
      typedef typename _Alloc_traits::const_pointer	const_pointer;
      typedef typename _Alloc_traits::reference		reference; //左值引用类型
      typedef typename _Alloc_traits::const_reference	const_reference;
      typedef typename _Base::iterator			iterator; //迭代器
      typedef typename _Base::const_iterator		const_iterator;
      typedef std::reverse_iterator<const_iterator>	const_reverse_iterator;
      typedef std::reverse_iterator<iterator>		reverse_iterator; //反向迭代器
      typedef size_t					size_type;
      typedef ptrdiff_t					difference_type; //元素之间的距离
      typedef _Alloc					allocator_type; //派生类内存分配器

    protected: //访问控制基类成员
      static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT
      { return __deque_buf_size(sizeof(_Tp)); }

      using _Base::_M_initialize_map;
      using _Base::_M_create_nodes;
      using _Base::_M_destroy_nodes;
      using _Base::_M_allocate_node;
      using _Base::_M_deallocate_node;
      using _Base::_M_allocate_map;
      using _Base::_M_deallocate_map;
      using _Base::_M_get_Tp_allocator;

      using _Base::_M_impl;

    public:
      deque() : _Base() { } //默认构造函数

      explicit //不可隐式类型转换
      deque(const allocator_type& __a)
      : _Base(__a, 0) { }

      explicit //不可隐式类型转换
      deque(size_type __n, const allocator_type& __a = allocator_type())
      : _Base(__a, __n)
      { _M_default_initialize(); }

      deque(size_type __n, const value_type& __value,
	    const allocator_type& __a = allocator_type())
      : _Base(__a, __n)
      { _M_fill_initialize(__value); } //内存分配并赋初值

      deque(const deque& __x) //拷贝构造函数
      : _Base(_Alloc_traits::_S_select_on_copy(__x._M_get_Tp_allocator()),
	      __x.size())
      { std::__uninitialized_copy_a(__x.begin(), __x.end(),
				    this->_M_impl._M_start,
				    _M_get_Tp_allocator()); }

      deque(deque&& __x) //移动构造函数
      : _Base(std::move(__x)) { }

      /// Copy constructor with alternative allocator
      deque(const deque& __x, const allocator_type& __a)
      : _Base(__a, __x.size())
      { std::__uninitialized_copy_a(__x.begin(), __x.end(),
				    this->_M_impl._M_start,
				    _M_get_Tp_allocator()); }

      /// Move constructor with alternative allocator
      deque(deque&& __x, const allocator_type& __a)
      : _Base(std::move(__x), __a, __x.size())
      {
		if (__x.get_allocator() != __a)
		  {
		    std::__uninitialized_move_a(__x.begin(), __x.end(),
						this->_M_impl._M_start,
						_M_get_Tp_allocator());
		    __x.clear();
		  }
      }

      deque(initializer_list<value_type> __l,
	    const allocator_type& __a = allocator_type())
      : _Base(__a)
      {
		_M_range_initialize(__l.begin(), __l.end(),
				    random_access_iterator_tag());
      }

      template<typename _InputIterator,
	       typename = std::_RequireInputIter<_InputIterator>>
	deque(_InputIterator __first, _InputIterator __last,
	      const allocator_type& __a = allocator_type())
	: _Base(__a)
	{ _M_initialize_dispatch(__first, __last, __false_type()); }

      ~deque()
      { _M_destroy_data(begin(), end(), _M_get_Tp_allocator()); }

      deque&
      operator=(const deque& __x);

      deque&
      operator=(deque&& __x) noexcept(_Alloc_traits::_S_always_equal())
      {
		using __always_equal = typename _Alloc_traits::is_always_equal;
		_M_move_assign1(std::move(__x), __always_equal{});
		return *this;
      }

      deque&
      operator=(initializer_list<value_type> __l)
      {
		_M_assign_aux(__l.begin(), __l.end(),
			      random_access_iterator_tag());
		return *this;
      }

      void
      assign(size_type __n, const value_type& __val)
      { _M_fill_assign(__n, __val); }

      template<typename _InputIterator,
	       typename = std::_RequireInputIter<_InputIterator>>
		void
		assign(_InputIterator __first, _InputIterator __last)
		{ _M_assign_dispatch(__first, __last, __false_type()); }

      void
      assign(initializer_list<value_type> __l)
      { _M_assign_aux(__l.begin(), __l.end(), random_access_iterator_tag()); }

      /// Get a copy of the memory allocation object.
      allocator_type
      get_allocator() const _GLIBCXX_NOEXCEPT
      { return _Base::get_allocator(); }

      //begin、end、rbegin、rend,省略返回const迭代器
      iterator
      begin() _GLIBCXX_NOEXCEPT
      { return this->_M_impl._M_start; } //当前缓冲区首位置
      iterator
      end() _GLIBCXX_NOEXCEPT
      { return this->_M_impl._M_finish; } //当前缓冲区尾位置
      reverse_iterator
      rbegin() _GLIBCXX_NOEXCEPT
      { return reverse_iterator(this->_M_impl._M_finish); }
      reverse_iterator
      rend() _GLIBCXX_NOEXCEPT
      { return reverse_iterator(this->_M_impl._M_start); }
   
      //cbegin、cend、crbegin、crend
      const_iterator
      cbegin() const noexcept
      { return this->_M_impl._M_start; }
      const_iterator
      cend() const noexcept
      { return this->_M_impl._M_finish; }
      const_reverse_iterator
      crbegin() const noexcept
      { return const_reverse_iterator(this->_M_impl._M_finish); }
      const_reverse_iterator
      crend() const noexcept
      { return const_reverse_iterator(this->_M_impl._M_start); }

      size_type
      size() const _GLIBCXX_NOEXCEPT //调用iterator::operator-
      { return this->_M_impl._M_finish - this->_M_impl._M_start; }

      size_type
      max_size() const _GLIBCXX_NOEXCEPT
      { return _Alloc_traits::max_size(_M_get_Tp_allocator()); }

      void
      resize(size_type __new_size)
      {
		const size_type __len = size();
		if (__new_size > __len)
		  _M_default_append(__new_size - __len);
		else if (__new_size < __len)
		  _M_erase_at_end(this->_M_impl._M_start
				  + difference_type(__new_size));
      }

      void
      resize(size_type __new_size, const value_type& __x)
      {
		const size_type __len = size();
		if (__new_size > __len)
		  _M_fill_insert(this->_M_impl._M_finish, __new_size - __len, __x);
		else if (__new_size < __len)
		  _M_erase_at_end(this->_M_impl._M_start
				  + difference_type(__new_size));
      }

      void
      shrink_to_fit() noexcept
      { _M_shrink_to_fit(); }

      bool
      empty() const _GLIBCXX_NOEXCEPT
      { return this->_M_impl._M_finish == this->_M_impl._M_start; }

      // element access
      reference
      operator[](size_type __n) _GLIBCXX_NOEXCEPT
      {
		__glibcxx_requires_subscript(__n);
		return this->_M_impl._M_start[difference_type(__n)];
      }

      const_reference
      operator[](size_type __n) const _GLIBCXX_NOEXCEPT
      {
		__glibcxx_requires_subscript(__n);
		return this->_M_impl._M_start[difference_type(__n)];
      }

    protected:
      /// Safety check used only from at().
      void
      _M_range_check(size_type __n) const
      {
		if (__n >= this->size())
		  __throw_out_of_range_fmt(__N("deque::_M_range_check: __n "
					       "(which is %zu)>= this->size() "
					       "(which is %zu)"),
					   __n, this->size());
      }

    public:
      reference
      at(size_type __n)
      {
		_M_range_check(__n);
		return (*this)[__n];
      }

      const_reference
      at(size_type __n) const
      {
		_M_range_check(__n);
		return (*this)[__n];
      }

      reference
      front() _GLIBCXX_NOEXCEPT
      {
		__glibcxx_requires_nonempty();
		return *begin(); //返回首元素
      }

      reference
      back() _GLIBCXX_NOEXCEPT
      {
		__glibcxx_requires_nonempty();
		iterator __tmp = end();
		--__tmp; //调用_Deque_iterator::operator--
		return *__tmp; //返回尾元素
      }

      // [23.2.1.2] modifiers
      void
      push_front(const value_type& __x)
      {
		if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first)
		  {
		    _Alloc_traits::construct(this->_M_impl,
					     this->_M_impl._M_start._M_cur - 1,
					     __x);
		    --this->_M_impl._M_start._M_cur;
		  }
		else
		  _M_push_front_aux(__x);
      }

      void
      push_front(value_type&& __x)
      { emplace_front(std::move(__x)); }

      template<typename... _Args>
		void
		emplace_front(_Args&&... __args);

      void
      push_back(const value_type& __x)
      {
		if (this->_M_impl._M_finish._M_cur
		    != this->_M_impl._M_finish._M_last - 1)
		  {
		    _Alloc_traits::construct(this->_M_impl,
					     this->_M_impl._M_finish._M_cur, __x);
		    ++this->_M_impl._M_finish._M_cur;
		  }
		else
		  _M_push_back_aux(__x);
      }

      void
      push_back(value_type&& __x)
      { emplace_back(std::move(__x)); }

      template<typename... _Args>
		void
		emplace_back(_Args&&... __args);

      void
      pop_front() _GLIBCXX_NOEXCEPT
      {
		__glibcxx_requires_nonempty();
		if (this->_M_impl._M_start._M_cur
		    != this->_M_impl._M_start._M_last - 1)
		  {
		    _Alloc_traits::destroy(this->_M_impl,
					   this->_M_impl._M_start._M_cur);
		    ++this->_M_impl._M_start._M_cur;
		  }
		else
		  _M_pop_front_aux();
      }

      void
      pop_back() _GLIBCXX_NOEXCEPT
      {
		__glibcxx_requires_nonempty();
		if (this->_M_impl._M_finish._M_cur
		    != this->_M_impl._M_finish._M_first)
		  {
		    --this->_M_impl._M_finish._M_cur;
		    _Alloc_traits::destroy(this->_M_impl,
					   this->_M_impl._M_finish._M_cur);
		  }
		else
		  _M_pop_back_aux();
      }

      template<typename... _Args>
		iterator
		emplace(const_iterator __position, _Args&&... __args);

      iterator
      insert(const_iterator __position, const value_type& __x);

      iterator
      insert(const_iterator __position, value_type&& __x)
      { return emplace(__position, std::move(__x)); }

      iterator
      insert(const_iterator __p, initializer_list<value_type> __l)
      {
		auto __offset = __p - cbegin();
		_M_range_insert_aux(__p._M_const_cast(), __l.begin(), __l.end(),
				    std::random_access_iterator_tag());
		return begin() + __offset;
      }

      iterator
      insert(const_iterator __position, size_type __n, const value_type& __x)
      {
		difference_type __offset = __position - cbegin();
		_M_fill_insert(__position._M_const_cast(), __n, __x);
		return begin() + __offset;
      }

      template<typename _InputIterator,
	       typename = std::_RequireInputIter<_InputIterator>>
		iterator
		insert(const_iterator __position, _InputIterator __first,
		       _InputIterator __last)
		{
		  difference_type __offset = __position - cbegin();
		  _M_insert_dispatch(__position._M_const_cast(),
				     __first, __last, __false_type());
		  return begin() + __offset;
		}

      iterator
      erase(const_iterator __position)
      { return _M_erase(__position._M_const_cast()); }

      iterator
      erase(const_iterator __first, const_iterator __last)
      { return _M_erase(__first._M_const_cast(), __last._M_const_cast()); }

      void
      swap(deque& __x) _GLIBCXX_NOEXCEPT
      {
		__glibcxx_assert(_Alloc_traits::propagate_on_container_swap::value
				 || _M_get_Tp_allocator() == __x._M_get_Tp_allocator());
		_M_impl._M_swap_data(__x._M_impl);
		_Alloc_traits::_S_on_swap(_M_get_Tp_allocator(),
					  __x._M_get_Tp_allocator());
      }

      void
      clear() _GLIBCXX_NOEXCEPT
      { _M_erase_at_end(begin()); }
    }; //deque

  template<typename _Tp, typename _Alloc>
    inline bool
    operator==(const deque<_Tp, _Alloc>& __x,
                         const deque<_Tp, _Alloc>& __y)
    { return __x.size() == __y.size()
	     && std::equal(__x.begin(), __x.end(), __y.begin()); }

  template<typename _Tp, typename _Alloc>
    inline bool
    operator<(const deque<_Tp, _Alloc>& __x,
	      const deque<_Tp, _Alloc>& __y)
    { return std::lexicographical_compare(__x.begin(), __x.end(),
					  __y.begin(), __y.end()); }

  /// Based on operator==
  template<typename _Tp, typename _Alloc>
    inline bool
    operator!=(const deque<_Tp, _Alloc>& __x,
	       const deque<_Tp, _Alloc>& __y)
    { return !(__x == __y); }

  /// Based on operator<
  template<typename _Tp, typename _Alloc>
    inline bool
    operator>(const deque<_Tp, _Alloc>& __x,
	      const deque<_Tp, _Alloc>& __y)
    { return __y < __x; }

  /// Based on operator<
  template<typename _Tp, typename _Alloc>
    inline bool
    operator<=(const deque<_Tp, _Alloc>& __x,
	       const deque<_Tp, _Alloc>& __y)
    { return !(__y < __x); }

  /// Based on operator<
  template<typename _Tp, typename _Alloc>
    inline bool
    operator>=(const deque<_Tp, _Alloc>& __x,
	       const deque<_Tp, _Alloc>& __y)
    { return !(__x < __y); }

  /// See std::deque::swap().
  template<typename _Tp, typename _Alloc>
    inline void
    swap(deque<_Tp,_Alloc>& __x, deque<_Tp,_Alloc>& __y)
    _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y)))
    { __x.swap(__y); }

} // namespace std
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值