⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stl_deque.h

📁 gcc3.2.1源代码
💻 H
📖 第 1 页 / 共 4 页
字号:
                             _Alloc_traits<_Tp, _Alloc>::_S_instanceless>          _Base;  typedef typename _Base::allocator_type             allocator_type;  typedef _Deque_iterator<_Tp,_Tp&,_Tp*>             iterator;  typedef _Deque_iterator<_Tp,const _Tp&,const _Tp*> const_iterator;  _Deque_base(const allocator_type& __a, size_t __num_elements)    : _Base(__a), _M_start(), _M_finish()    { _M_initialize_map(__num_elements); }  _Deque_base(const allocator_type& __a)     : _Base(__a), _M_start(), _M_finish() {}  ~_Deque_base();    protected:  void _M_initialize_map(size_t);  void _M_create_nodes(_Tp** __nstart, _Tp** __nfinish);  void _M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish);  enum { _S_initial_map_size = 8 };protected:  iterator _M_start;  iterator _M_finish;};template <class _Tp, class _Alloc>_Deque_base<_Tp,_Alloc>::~_Deque_base(){  if (_M_map) {    _M_destroy_nodes(_M_start._M_node, _M_finish._M_node + 1);    _M_deallocate_map(_M_map, _M_map_size);  }}/** *  @if maint *  @brief Layout storage. *  @param  num_elements  The count of T's for which to allocate space at first. *  @return   Nothing. * *  The initial underlying memory layout is a bit complicated... *  @endif*/template <class _Tp, class _Alloc>void_Deque_base<_Tp,_Alloc>::_M_initialize_map(size_t __num_elements){  size_t __num_nodes =     __num_elements / __deque_buf_size(sizeof(_Tp)) + 1;  _M_map_size = max((size_t) _S_initial_map_size, __num_nodes + 2);  _M_map = _M_allocate_map(_M_map_size);  _Tp** __nstart = _M_map + (_M_map_size - __num_nodes) / 2;  _Tp** __nfinish = __nstart + __num_nodes;      try     { _M_create_nodes(__nstart, __nfinish); }  catch(...)    {      _M_deallocate_map(_M_map, _M_map_size);      _M_map = 0;      _M_map_size = 0;      __throw_exception_again;    }    _M_start._M_set_node(__nstart);  _M_finish._M_set_node(__nfinish - 1);  _M_start._M_cur = _M_start._M_first;  _M_finish._M_cur = _M_finish._M_first +               __num_elements % __deque_buf_size(sizeof(_Tp));}template <class _Tp, class _Alloc>void _Deque_base<_Tp,_Alloc>::_M_create_nodes(_Tp** __nstart, _Tp** __nfinish){  _Tp** __cur;  try {    for (__cur = __nstart; __cur < __nfinish; ++__cur)      *__cur = _M_allocate_node();  }  catch(...)    {       _M_destroy_nodes(__nstart, __cur);      __throw_exception_again;     }}template <class _Tp, class _Alloc>void_Deque_base<_Tp,_Alloc>::_M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish){  for (_Tp** __n = __nstart; __n < __nfinish; ++__n)    _M_deallocate_node(*__n);}/** *  @ingroup Containers *  @ingroup Sequences * *  Meets the requirements of a <a href="tables.html#65">container</a>, a *  <a href="tables.html#66">reversible container</a>, and a *  <a href="tables.html#67">sequence</a>, including the *  <a href="tables.html#68">optional sequence requirements</a>. * *  Placeholder:  see http://www.sgi.com/tech/stl/Deque.html for now. * *  In previous HP/SGI versions of deque, there was an extra template parameter *  so users could control the node size.  This extension turned out to violate *  the C++ standard (it can be detected using template template parameters), *  and it was removed. * *  @if maint *  Here's how a deque<Tp> manages memory.  Each deque has 4 members: *   *  - Tp**        _M_map *  - size_t      _M_map_size *  - iterator    _M_start, _M_finish *   *  map_size is at least 8.  %map is an array of map_size pointers-to-"nodes". *  (The name has nothing to do with the std::map class.) *   *  A "node" has no specific type name as such, but it is referred to as *  "node" in this file.  It is a simple array-of-Tp.  If Tp is very large, *  there will be one Tp element per node (i.e., an "array" of one). *  For non-huge Tp's, node size is inversely related to Tp size:  the *  larger the Tp, the fewer Tp's will fit in a node.  The goal here is to *  keep the total size of a node relatively small and constant over different *  Tp's, to improve allocator efficiency. *   *  **** As I write this, the nodes are /not/ allocated using the high-speed *  memory pool.  There are 20 hours left in the year; perhaps I can fix *  this before 2002. *   *  Not every pointer in the %map array will point to a node.  If the initial *  number of elements in the deque is small, the /middle/ %map pointers will *  be valid, and the ones at the edges will be unused.  This same situation *  will arise as the %map grows:  available %map pointers, if any, will be on *  the ends.  As new nodes are created, only a subset of the %map's pointers *  need to be copied "outward". * *  Class invariants: * - For any nonsingular iterator i: *    - i.node points to a member of the %map array.  (Yes, you read that *      correctly:  i.node does not actually point to a node.)  The member of *      the %map array is what actually points to the node. *    - i.first == *(i.node)    (This points to the node (first Tp element).) *    - i.last  == i.first + node_size *    - i.cur is a pointer in the range [i.first, i.last).  NOTE: *      the implication of this is that i.cur is always a dereferenceable *      pointer, even if i is a past-the-end iterator. * - Start and Finish are always nonsingular iterators.  NOTE: this means that *   an empty deque must have one node, a deque with <N elements (where N is *   the node buffer size) must have one node, a deque with N through (2N-1) *   elements must have two nodes, etc. * - For every node other than start.node and finish.node, every element in the *   node is an initialized object.  If start.node == finish.node, then *   [start.cur, finish.cur) are initialized objects, and the elements outside *   that range are uninitialized storage.  Otherwise, [start.cur, start.last) *   and [finish.first, finish.cur) are initialized objects, and [start.first, *   start.cur) and [finish.cur, finish.last) are uninitialized storage. * - [%map, %map + map_size) is a valid, non-empty range.   * - [start.node, finish.node] is a valid range contained within  *   [%map, %map + map_size).   * - A pointer in the range [%map, %map + map_size) points to an allocated node *   if and only if the pointer is in the range [start.node, finish.node]. * *  Here's the magic:  nothing in deque is "aware" of the discontiguous storage! * *  The memory setup and layout occurs in the parent, _Base, and the iterator *  class is entirely responsible for "leaping" from one node to the next.  All *  the implementation routines for deque itself work only through the start *  and finish iterators.  This keeps the routines simple and sane, and we can *  use other standard algorithms as well. *  @endif*/template <class _Tp, class _Alloc = allocator<_Tp> >class deque : protected _Deque_base<_Tp, _Alloc>{  // concept requirements  __glibcpp_class_requires(_Tp, _SGIAssignableConcept)  typedef _Deque_base<_Tp, _Alloc> _Base;public:  typedef _Tp                                value_type;  typedef value_type*                        pointer;  typedef const value_type*                  const_pointer;  typedef value_type&                        reference;  typedef const value_type&                  const_reference;  typedef size_t                             size_type;  typedef ptrdiff_t                          difference_type;  typedef typename _Base::allocator_type allocator_type;  allocator_type get_allocator() const { return _Base::get_allocator(); }  typedef typename _Base::iterator           iterator;  typedef typename _Base::const_iterator     const_iterator;  typedef reverse_iterator<const_iterator>   const_reverse_iterator;  typedef reverse_iterator<iterator>         reverse_iterator;protected:  typedef pointer* _Map_pointer;  static size_t _S_buffer_size() { return __deque_buf_size(sizeof(_Tp)); }  // Functions controlling memory layout, and nothing else.  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;  /** @if maint   *  A total of four data members accumulated down the heirarchy.  If the   *  _Alloc type requires separate instances, then two of them will also be   *  included in each deque.   *  @endif  */  using _Base::_M_map;  using _Base::_M_map_size;  using _Base::_M_start;  using _Base::_M_finish;public:                         // Basic accessors  iterator begin() { return _M_start; }  iterator end() { return _M_finish; }  const_iterator begin() const { return _M_start; }  const_iterator end() const { return _M_finish; }  reverse_iterator rbegin() { return reverse_iterator(_M_finish); }  reverse_iterator rend() { return reverse_iterator(_M_start); }  const_reverse_iterator rbegin() const     { return const_reverse_iterator(_M_finish); }  const_reverse_iterator rend() const     { return const_reverse_iterator(_M_start); }  reference operator[](size_type __n)    { return _M_start[difference_type(__n)]; }  const_reference operator[](size_type __n) const     { return _M_start[difference_type(__n)]; }  void _M_range_check(size_type __n) const {    if (__n >= this->size())      __throw_out_of_range("deque");  }  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() { return *_M_start; }  reference back() {    iterator __tmp = _M_finish;    --__tmp;    return *__tmp;  }  const_reference front() const { return *_M_start; }  const_reference back() const {    const_iterator __tmp = _M_finish;    --__tmp;    return *__tmp;  }  size_type size() const { return _M_finish - _M_start; }  size_type max_size() const { return size_type(-1); }  bool empty() const { return _M_finish == _M_start; }public:                         // Constructor, destructor.  explicit deque(const allocator_type& __a = allocator_type())     : _Base(__a, 0) {}  deque(const deque& __x) : _Base(__x.get_allocator(), __x.size())     { uninitialized_copy(__x.begin(), __x.end(), _M_start); }  deque(size_type __n, const value_type& __value,        const allocator_type& __a = allocator_type()) : _Base(__a, __n)    { _M_fill_initialize(__value); }  explicit  deque(size_type __n)  : _Base(allocator_type(), __n)  { _M_fill_initialize(value_type()); }  // Check whether it's an integral type.  If so, it's not an iterator.  template<class _InputIterator>    deque(_InputIterator __first, _InputIterator __last,          const allocator_type& __a = allocator_type())    : _Base(__a)    {      typedef typename _Is_integer<_InputIterator>::_Integral _Integral;      _M_initialize_dispatch(__first, __last, _Integral());    }  template<class _Integer>    void    _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type)    {      _M_initialize_map(__n);      _M_fill_initialize(__x);    }  template<class _InputIter>    void    _M_initialize_dispatch(_InputIter __first, _InputIter __last, __false_type)    {      typedef typename iterator_traits<_InputIter>::iterator_category _IterCategory;      _M_range_initialize(__first, __last, _IterCategory());    }  ~deque()  { _Destroy(_M_start, _M_finish); }  deque& operator= (const deque& __x) {    const size_type __len = size();    if (&__x != this) {      if (__len >= __x.size())        erase(copy(__x.begin(), __x.end(), _M_start), _M_finish);      else {        const_iterator __mid = __x.begin() + difference_type(__len);        copy(__x.begin(), __mid, _M_start);        insert(_M_finish, __mid, __x.end());      }    }    return *this;  }          void swap(deque& __x) {    std::swap(_M_start, __x._M_start);    std::swap(_M_finish, __x._M_finish);    std::swap(_M_map, __x._M_map);    std::swap(_M_map_size, __x._M_map_size);  }public:   // assign(), a generalized assignment member function.  Two  // versions: one that takes a count, and one that takes a range.  // The range version is a member template, so we dispatch on whether  // or not the type is an integer.  void _M_fill_assign(size_type __n, const _Tp& __val) {    if (__n > size()) {      fill(begin(), end(), __val);      insert(end(), __n - size(), __val);    }    else {      erase(begin() + __n, end());      fill(begin(), end(), __val);    }  }  void  assign(size_type __n, const _Tp& __val)  { _M_fill_assign(__n, __val); }  template<class _InputIterator>    void    assign(_InputIterator __first, _InputIterator __last)    {      typedef typename _Is_integer<_InputIterator>::_Integral _Integral;      _M_assign_dispatch(__first, __last, _Integral());    }private:                        // helper functions for assign()   template<class _Integer>    void    _M_assign_dispatch(_Integer __n, _Integer __val, __true_type)    { _M_fill_assign(static_cast<size_type>(__n), static_cast<_Tp>(__val)); }  template<class _InputIterator>    void    _M_assign_dispatch(_InputIterator __first, _InputIterator __last, __false_type)    {      typedef typename iterator_traits<_InputIterator>::iterator_category _IterCategory;      _M_assign_aux(__first, __last, _IterCategory());    }  template <class _InputIterator>  void _M_assign_aux(_InputIterator __first, _InputIterator __last,                     input_iterator_tag);  template <class _ForwardIterator>  void _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last,                     forward_iterator_tag) {    size_type __len = distance(__first, __last);    if (__len > size()) {      _ForwardIterator __mid = __first;      advance(__mid, size());      copy(__first, __mid, begin());      insert(end(), __mid, __last);    }    else      erase(copy(__first, __last, begin()), end());  }public:                         // push_* and pop_*    void  push_back(const value_type& __t)  {    if (_M_finish._M_cur != _M_finish._M_last - 1) {      _Construct(_M_finish._M_cur, __t);      ++_M_finish._M_cur;    }    else      _M_push_back_aux(__t);  }  void  push_back()  {    if (_M_finish._M_cur != _M_finish._M_last - 1) {      _Construct(_M_finish._M_cur);      ++_M_finish._M_cur;    }    else      _M_push_back_aux();  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -