Chinaunix首页 | 论坛 | 博客
  • 博客访问: 243604
  • 博文数量: 253
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 3
  • 用 户 组: 普通用户
  • 注册时间: 2014-09-21 12:29
文章分类

全部博文(253)

文章存档

2014年(253)

我的朋友

分类: C/C++

2014-09-21 12:53:35

原文地址:STL源码剖析—list(3) 作者:andyhzw

操作系统:ubuntu10.04
STL源码版本:2.91


前言:
    通过前面的两个章节,大概对stl的架构有个基础的了解,那么接下来应该怎么做呢:
    应该从应用的角度,也就是最上层的应用,来看 list是如何被使用,在一步步深入。

1,list的接口:
    1.1)list的各个接口的使用用例,请看:
             

c++ stl list使用总结



    1.2)由上面可得,list的类定义为:
        文件list是调用list接口的#include文件。

点击(此处)折叠或打开 《文件list》

  1. #ifndef __SGI_STL_LIST
  2. #define __SGI_STL_LIST

  3. #include <stl_algobase.h>
  4. #include <stl_alloc.h>
  5. #include <stl_construct.h>
  6. #include <stl_uninitialized.h>
  7. #include <stl_list.h>

  8. #endif /* __SGI_STL_LIST */

        1.2.1)list接口真正定义在 文件中
            对于 typedef 在类中的定义有疑问的请看:c++的类中typedef的作用 

点击(此处)折叠或打开

  1. template <class T, class Alloc = alloc>
  2. class list {
  3. protected:
  4.   typedef void* void_pointer;
  5.   typedef __list_node<T> list_node;
  6.   typedef simple_alloc<list_node, Alloc> list_node_allocator;
  7. public:
  8.   typedef T value_type;
  9.   typedef value_type* pointer;
  10.   typedef const value_type* const_pointer;
  11.   typedef value_type& reference;
  12.   typedef const value_type& const_reference;
  13.   typedef list_node* link_type;
  14.   typedef size_t size_type;
  15.   typedef ptrdiff_t difference_type;

  16. public:
  17.   typedef __list_iterator<T, T&, T*> iterator;
  18.   typedef __list_iterator<T, const T&, const T*> const_iterator;

  19.   typedef reverse_iterator<const_iterator> const_reverse_iterator;
  20.   typedef reverse_iterator<iterator> reverse_iterator;

  21. protected:
  22.   link_type get_node() { return list_node_allocator::allocate(); }
  23.   void put_node(link_type p) { list_node_allocator::deallocate(p); }

  24.   link_type create_node(const T& x) {
  25.     link_type p = get_node();
  26.     __STL_TRY {
  27.       construct(&p->data, x);
  28.     }
  29.     __STL_UNWIND(put_node(p));
  30.     return p;
  31.   }
  32.   void destroy_node(link_type p) {
  33.     destroy(&p->data);
  34.     put_node(p);
  35.   }

  36. protected:
  37.   void empty_initialize() {
  38.     node = get_node();
  39.     node->next = node;
  40.     node->prev = node;
  41.   }

  42.   void fill_initialize(size_type n, const T& value) {
  43.     empty_initialize();
  44.     __STL_TRY {
  45.       insert(begin(), n, value);
  46.     }
  47.     __STL_UNWIND(clear(); put_node(node));
  48.   }

  49.   template <class InputIterator>
  50.   void range_initialize(InputIterator first, InputIterator last) {
  51.     empty_initialize();
  52.     __STL_TRY {
  53.       insert(begin(), first, last);
  54.     }
  55.     __STL_UNWIND(clear(); put_node(node));
  56.   }

  57. protected:
  58.   link_type node;

  59. public:
  60.   list() { empty_initialize(); }

  61.   iterator begin() { return (link_type)((*node).next); }
  62.   const_iterator begin() const { return (link_type)((*node).next); }
  63.   iterator end() { return node; }
  64.   const_iterator end() const { return node; }
  65.   reverse_iterator rbegin() { return reverse_iterator(end()); }
  66.   const_reverse_iterator rbegin() const {
  67.     return const_reverse_iterator(end());
  68.   }
  69.   reverse_iterator rend() { return reverse_iterator(begin()); }
  70.   const_reverse_iterator rend() const {
  71.     return const_reverse_iterator(begin());
  72.   }
  73.   bool empty() const { return node->next == node; }
  74.   size_type size() const {
  75.     size_type result = 0;
  76.     distance(begin(), end(), result);
  77.     return result;
  78.   }
  79.   size_type max_size() const { return size_type(-1); }
  80.   reference front() { return *begin(); }
  81.   const_reference front() const { return *begin(); }
  82.   reference back() { return *(--end()); }
  83.   const_reference back() const { return *(--end()); }
  84.   void swap(list<T, Alloc>& x) { __STD::swap(node, x.node); }
  85.   iterator insert(iterator position, const T& x) {
  86.     link_type tmp = create_node(x);
  87.     tmp->next = position.node;
  88.     tmp->prev = position.node->prev;
  89.     (link_type(position.node->prev))->next = tmp;
  90.     position.node->prev = tmp;
  91.     return tmp;
  92.   }
  93.   iterator insert(iterator position) { return insert(position, T()); }

  94.   template <class InputIterator>
  95.   void insert(iterator position, InputIterator first, InputIterator last);

  96.   void insert(iterator pos, size_type n, const T& x);
  97.   void insert(iterator pos, int n, const T& x) {
  98.     insert(pos, (size_type)n, x);
  99.   }
  100.   void insert(iterator pos, long n, const T& x) {
  101.     insert(pos, (size_type)n, x);
  102.   }

  103.   void push_front(const T& x) { insert(begin(), x); }
  104.   void push_back(const T& x) { insert(end(), x); }
  105.   iterator erase(iterator position) {
  106.     link_type next_node = link_type(position.node->next);
  107.     link_type prev_node = link_type(position.node->prev);
  108.     prev_node->next = next_node;
  109.     next_node->prev = prev_node;
  110.     destroy_node(position.node);
  111.     return iterator(next_node);
  112.   }
  113.   iterator erase(iterator first, iterator last);
  114.   void resize(size_type new_size, const T& x);
  115.   void resize(size_type new_size) { resize(new_size, T()); }
  116.   void clear();

  117.   void pop_front() { erase(begin()); }
  118.   void pop_back() {
  119.     iterator tmp = end();
  120.     erase(--tmp);
  121.   }
  122.   list(size_type n, const T& value) { fill_initialize(n, value); }
  123.   list(int n, const T& value) { fill_initialize(n, value); }
  124.   list(long n, const T& value) { fill_initialize(n, value); }
  125.   explicit list(size_type n) { fill_initialize(n, T()); }

  126. #ifdef __STL_MEMBER_TEMPLATES
  127.   template <class InputIterator>
  128.   list(InputIterator first, InputIterator last) {
  129.     range_initialize(first, last);
  130.   }

  131.   list(const list<T, Alloc>& x) {
  132.     range_initialize(x.begin(), x.end());
  133.   }
  134.   ~list() {
  135.     clear();
  136.     put_node(node);
  137.   }
  138.   list<T, Alloc>& operator=(const list<T, Alloc>& x);

  139. protected:
  140.   void transfer(iterator position, iterator first, iterator last) {
  141.     if (position != last) {
  142.       (*(link_type((*last.node).prev))).next = position.node;
  143.       (*(link_type((*first.node).prev))).next = last.node;
  144.       (*(link_type((*position.node).prev))).next = first.node;
  145.       link_type tmp = link_type((*position.node).prev);
  146.       (*position.node).prev = (*last.node).prev;
  147.       (*last.node).prev = (*first.node).prev;
  148.       (*first.node).prev = tmp;
  149.     }
  150.   }

  151. public:
  152.   void splice(iterator position, list& x) {
  153.     if (!x.empty())
  154.       transfer(position, x.begin(), x.end());
  155.   }
  156.   void splice(iterator position, list&, iterator i) {
  157.     iterator j = i;
  158.     ++j;
  159.     if (position == i || position == j) return;
  160.     transfer(position, i, j);
  161.   }
  162.   void splice(iterator position, list&, iterator first, iterator last) {
  163.     if (first != last)
  164.       transfer(position, first, last);
  165.   }
  166.   void remove(const T& value);
  167.   void unique();
  168.   void merge(list& x);
  169.   void reverse();
  170.   void sort();

  171.   template <class Predicate> void remove_if(Predicate);
  172.   template <class BinaryPredicate> void unique(BinaryPredicate);
  173.   template <class StrictWeakOrdering> void merge(list&, StrictWeakOrdering);
  174.   template <class StrictWeakOrdering> void sort(StrictWeakOrdering);

  175.   friend bool operator== __STL_NULL_TMPL_ARGS (const list& x, const list& y);
  176. };

  2空间配置器 allocate
    在看class list的过程中,需要了解的第一个要点是 空间配置器 allocate,其实现内存的动态分配。

点击(此处)折叠或打开

  1. template<class T, class Alloc>
  2. class simple_alloc {

  3. public:
  4.     static T *allocate(size_t n)
  5.                 { return 0 == n? 0 : (T*) Alloc::allocate(n * sizeof (T)); }
  6.     static T *allocate(void)
  7.                 { return (T*) Alloc::allocate(sizeof (T)); }
  8.     static void deallocate(T *p, size_t n)
  9.                 { if (0 != n) Alloc::deallocate(p, n * sizeof (T)); }
  10.     static void deallocate(T *p)
  11.                 { Alloc::deallocate(p, sizeof (T)); }
  12. };
        内存的真正的动态分配的实现在:

点击(此处)折叠或打开 >

  1. typedef __default_alloc_template<__NODE_ALLOCATOR_THREADS, 0> alloc;
      在ubuntu10.04中的gcc使用的宏定义中可知:

点击(此处)折叠或打开

  1. # ifdef __STL_PTHREADS
  2. # include <pthread.h>
  3. # define __NODE_ALLOCATOR_THREADS true
  4. # endif

点击(此处)折叠或打开

  1. template <bool threads, int inst>  //
  2. class __default_alloc_template {

  3. private:
  4.   static size_t ROUND_UP(size_t bytes) {
  5.         return (((bytes) + __ALIGN-1) & ~(__ALIGN - 1));
  6.   }
  7. __PRIVATE:
  8.   union obj {
  9.         union obj * free_list_link;
  10.         char client_data[1]; /* The client sees this. */
  11.   };
  12. private:
  13.     static obj * __VOLATILE free_list[__NFREELISTS];

  14.   static size_t FREELIST_INDEX(size_t bytes) {
  15.         return (((bytes) + __ALIGN-1)/__ALIGN - 1);
  16.   }

  17.   // Returns an object of size n, and optionally adds to size n free list.
  18.   static void *refill(size_t n);
  19.   // Allocates a chunk for nobjs of size "size". nobjs may be reduced
  20.   // if it is inconvenient to allocate the requested number.
  21.   static char *chunk_alloc(size_t size, int &nobjs);

  22.   // Chunk allocation state.
  23.   static char *start_free;
  24.   static char *end_free;
  25.   static size_t heap_size;

  26.   static pthread_mutex_t __node_allocator_lock;

  27.     class lock {
  28.         public:
  29.             lock() { __NODE_ALLOCATOR_LOCK; }
  30.             ~lock() { __NODE_ALLOCATOR_UNLOCK; }
  31.     };
  32.     friend class lock;

  33. public:

  34.   /* n must be > 0 */
  35.   static void * allocate(size_t n)
  36.   {
  37.     obj * __VOLATILE * my_free_list;
  38.     obj * __RESTRICT result;

  39.     if (n > (size_t) __MAX_BYTES) {
  40.         return(malloc_alloc::allocate(n));
  41.     }
  42.     my_free_list = free_list + FREELIST_INDEX(n);
  43.     // Acquire the lock here with a constructor call.
  44.     // This ensures that it is released in exit or during stack
  45.     // unwinding.

  46.         lock lock_instance;

  47.     result = *my_free_list;
  48.     if (result == 0) {
  49.         void *r = refill(ROUND_UP(n));
  50.         return r;
  51.     }
  52.     *my_free_list = result -> free_list_link;
  53.     return (result);
  54.   };

  55.   /* p may not be 0 */
  56.   static void deallocate(void *p, size_t n)
  57.   {
  58.     obj *q = (obj *)p;
  59.     obj * __VOLATILE * my_free_list;

  60.     if (n > (size_t) __MAX_BYTES) {
  61.         malloc_alloc::deallocate(p, n);
  62.         return;
  63.     }
  64.     my_free_list = free_list + FREELIST_INDEX(n);
  65.     // acquire lock

  66.         /*REFERENCED*/
  67.         lock lock_instance;

  68.     q -> free_list_link = *my_free_list;
  69.     *my_free_list = q;
  70.     // lock is released here
  71.   }

  72.   static void * reallocate(void *p, size_t old_sz, size_t new_sz);

  73. } ;
    malloc_alloc定义如下:

点击(此处)折叠或打开

  1. typedef __malloc_alloc_template<0> malloc_alloc;

点击(此处)折叠或打开

  1. template <int inst>
  2. class __malloc_alloc_template {

  3. private:

  4. static void *oom_malloc(size_t);

  5. static void *oom_realloc(void *, size_t);

  6. #ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG
  7.     static void (* __malloc_alloc_oom_handler)();
  8. #endif

  9. public:

  10. static void * allocate(size_t n)
  11. {
  12.     void *result = malloc(n);
  13.     if (0 == result) result = oom_malloc(n);
  14.     return result;
  15. }

  16. static void deallocate(void *p, size_t /* n */)
  17. {
  18.     free(p);
  19. }

  20. static void * reallocate(void *p, size_t /* old_sz */, size_t new_sz)
  21. {
  22.     void * result = realloc(p, new_sz);
  23.     if (0 == result) result = oom_realloc(p, new_sz);
  24.     return result;
  25. }

  26. static void (* set_malloc_handler(void (*f)()))()
  27. {
  28.     void (* old)() = __malloc_alloc_oom_handler;
  29.     __malloc_alloc_oom_handler = f;
  30.     return(old);
  31. }

  32. };

3,__list_node的定义:

点击(此处)折叠或打开

  1. template <class T>
  2. struct __list_node {
  3.   typedef void* void_pointer;
  4.   void_pointer next;
  5.   void_pointer prev;
  6.   T data;
  7. };

4,__list_iterator的定义:

点击(此处)折叠或打开

  1. template<class T, class Ref, class Ptr>
  2. struct __list_iterator {
  3.   typedef __list_iterator<T, T&, T*> iterator;
  4.   typedef __list_iterator<T, const T&, const T*> const_iterator;
  5.   typedef __list_iterator<T, Ref, Ptr> self;

  6.   typedef bidirectional_iterator_tag iterator_category;
  7.   typedef T value_type;
  8.   typedef Ptr pointer;
  9.   typedef Ref reference;
  10.   typedef __list_node<T>* link_type;
  11.   typedef size_t size_type;
  12.   typedef ptrdiff_t difference_type;

  13.   link_type node;

  14.   __list_iterator(link_type x) : node(x) {}
  15.   __list_iterator() {}
  16.   __list_iterator(const iterator& x) : node(x.node) {}

  17.   bool operator==(const self& x) const { return node == x.node; }
  18.   bool operator!=(const self& x) const { return node != x.node; }
  19.   reference operator*() const { return (*node).data; }

  20.   pointer operator->() const { return &(operator*()); }

  21.   self& operator++() {
  22.     node = (link_type)((*node).next);
  23.     return *this;
  24.   }
  25.   self operator++(int) {
  26.     self tmp = *this;
  27.     ++*this;
  28.     return tmp;
  29.   }
  30.   self& operator--() {
  31.     node = (link_type)((*node).prev);
  32.     return *this;
  33.   }
  34.   self operator--(int) {
  35.     self tmp = *this;
  36.     --*this;
  37.     return tmp;
  38.   }
  39. };


  




阅读(306) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~