STL运用的C++技术(7)——代码整合

转载 2016年05月31日 11:02:40

本文将6篇文章中出现的代码整合在一起,主要参考了HP的STL源码。通过这些代码,不仅可以看到这些C++技术在STL中的运用,同时也能大致了解STL的架构组织及实现方法。首先给出一个测试用例,所有代码都是自定义的,未用到STL。读者可以建立一个C++工程,把这些代码加进去,就可以运行起来。方便之处在于,读者可以修改这些代码,实现一些自己的功能,以加深对于STL的理解。

        STL真正实现中,其实也就是对下述代码的扩展,定义更多的容器、算法、函数对象、迭代器等,至于具体实现的方法,仅仅是数据结构、算法自身上的差异,整体的实现步骤或者说是架构都是一样的。比如如果要实现deque,就需要定义deque的迭代器,deque的数据结构。又比如要实现排序算法,它与容器没有关系,它的形参是迭代器。因此实现起来根本不用考虑具体的容器。当然有些容器的排序算法需要特别实现,比如List的排序算法就是单独实现的。再比如要实现新的函数对象,没有问题,只需继承最基本的两个类,然后实现自定义的功能。

        当然,本文没有介绍STL的另一个重要组成部分,那就是内存的分配机制。感兴趣的读者可以看一下《STL源码剖析》这本书,或者找份源码看一下。

  1. #include "List.h"        //自定义的链表  
  2. #include "Algorithm.h"   //自定义的算法  
  3. #include "Functional.h"  //自定义的函数对象  
  4. #include <iostream>  
  5. using namespace std;  
  6.   
  7. //测试程序 VS2008下测试通过  
  8. int main()  
  9. {  
  10.     List<int> l;                                   //自定义的链表,STL链表的部分功能  
  11.     l.push_back(1);                                //链表功能测试  
  12.     l.push_back(2);  
  13.   
  14.     //测试 萃取迭代器的类型功能  
  15.     MyAdvance(l.begin(), 1);                                  //输出Random_access_iterator_tag  
  16.     //测试 萃取迭代器所指的数据类型  
  17.     Iterator_traits<int *>::value_type x = 5;                 //特化    
  18.     Iterator_traits<const int*>::value_type  y = 6;           //特化    
  19.     Iterator_traits<List<int>::iterator>::value_type z = 7;   //list 容器    
  20.     cout<<x<<' '<<y<<' '<<z<<endl;                            //输出5 6 7   
  21.   
  22.     //测试算法  
  23.     cout<<"before Iter_swap : "<<*(l.begin())<<' '<<*(++l.begin())<<endl; //输出1 2   
  24.     Iter_swap(l.begin(),++l.begin());                                    //交换两个迭代器的元素           
  25.     cout<<"after Iter_swap : "<<*(l.begin())<<' '<<*(++l.begin())<<endl; //输出2 1   
  26.   
  27.     l.push_front(3);                                  
  28.     l.push_front(4);  
  29.     l.push_front(5);                            
  30.     l.push_front(6);  
  31.   
  32.     //测试函数对象  
  33.     //链表中的元素为 6 5 4 3 1 2  
  34.     int count1 = Count_if(l.begin(), l.end(), bind2nd(less_equal<int>(), 10));       //求容器中小于等于10的元素个数    
  35.     int count2 = Count_if(l.begin(), l.end(), not1(bind2nd(less_equal<int>(), 10))); //求容器中不小于等于10的元素个数,正好是上面结果的取反    
  36.     cout<<count1<<' '<<count2<<endl;                                                 //输出6 0   
  37.   
  38.     int count3 = 0, count4 = 0;  
  39.     Count_if(l.begin(), l.end(), bind2nd(greater_equal<int>(), 3), count3);          //求容器中大于等于3的元素个数       
  40.     Count_if(l.begin(), l.end(), not1(bind2nd(greater_equal<int>(), 3)), count4);    //求容器中小于3的元素个数    
  41.     cout<<count3<<' '<<count4<<endl;                                                 //输出4 2   
  42.   
  43.     l.clear();  
  44.     return 0;  
  45. }  

      首先给出迭代器萃取剂的定义,代码如下。可以看到内嵌型别技术,模板特化技术,重载函数的精妙运用。

  1. //Iterator_traits.h  
  2. #pragma once   
  3.   
  4. //迭代器分类,大写已便于标准库区分  
  5. struct Input_iterator_tag {};    
  6. struct Output_iterator_tag {};    
  7. struct Forward_iterator_tag : public Input_iterator_tag {};    
  8. struct Bidirectional_iterator_tag : public Forward_iterator_tag {};    
  9. struct Random_access_iterator_tag : public Bidirectional_iterator_tag {};    
  10.   
  11. //萃取剂    
  12. template<class I>    
  13. struct Iterator_traits{    
  14.     typedef typename I::value_type value_type;    
  15.     typedef typename I::iterator_category iterator_category; //迭代器的类型    
  16.     typedef typename I::difference_type   difference_type;  
  17.     typedef typename I::pointer           pointer;  
  18.     typedef typename I::reference         reference;  
  19. };    
  20. //特化 原生指针    
  21. template<class T>    
  22. struct Iterator_traits<T*>{    
  23.     typedef T value_type;    
  24.     typedef Random_access_iterator_tag iterator_category;    
  25.     typedef ptrdiff_t                 difference_type;  
  26.     typedef T*                        pointer;  
  27.     typedef T&                        reference;  
  28. };    
  29. //特化 原生常指针    
  30. template<class T>    
  31. struct Iterator_traits<const T*>{    
  32.     typedef T value_type;    
  33.     typedef Random_access_iterator_tag iterator_category;    
  34.     typedef ptrdiff_t                 difference_type;  
  35.     typedef const T*                  pointer;  
  36.     typedef const T&                  reference;  
  37. };    
  38.   
  39. //萃取剂  
  40. #define VALUE_TYPE(I) Iterator_traits<I>::value_type()    
  41. #define ITERATOR_CATEGORY(I) Iterator_traits<I>::iterator_category()   
  42. #define DIFFERENCE_TYPE(I) Iterator_traits<I>::difference_type()     
  43. #define POINTER(I) Iterator_traits<I>::pointer()    
  44. #define REFERENCE(I) Iterator_traits<I>::reference()     
  45.   
  46. //自定义的advance函数,与STL差不多    
  47. template <class InputIterator, class Distance>    
  48. inline void MyAdvance(InputIterator &i, Distance n)     
  49. {    
  50.     _MyAdvance(i, n, ITERATOR_CATEGORY(InputIterator)); //萃取迭代器的类型    
  51. }    
  52. template <class InputIterator, class Distance>    
  53. inline void _MyAdvance(InputIterator& i, Distance n, Input_iterator_tag)     
  54. {    
  55.     while (n--) ++i;    
  56.     cout<<"InputIterator"<<endl;    
  57. }    
  58. template <class BidirectionalIterator, class Distance>    
  59. inline void _MyAdvance(BidirectionalIterator& i, Distance n, Bidirectional_iterator_tag)     
  60. {    
  61.     if (n >= 0)    
  62.         while (n--) ++i;    
  63.     else    
  64.         while (n++) --i;    
  65.     cout<<"BidirectionalIterator"<<endl;    
  66. }    
  67. template <class RandomAccessIterator, class Distance>    
  68. inline void _MyAdvance(RandomAccessIterator& i, Distance n, Random_access_iterator_tag)     
  69. {    
  70.     i += n;    
  71.     cout<<"RandomAccessIterator"<<endl;    
  72. }    
          再给出一个容器的定义,这里用的List,实现了STL的部分功能,同时还出了相应的迭代器的实现。可以看到大量的重载操作符的实现。

  1. //List_iterator.h  
  2. #pragma once  
  3. #include "Iterator_traits.h"  
  4.   
  5. //结点定义,双向链表    
  6. template <class T>    
  7. struct List_node {    
  8.     List_node* next;    
  9.     List_node* prev;    
  10.     T data;    
  11. };    
  12. //链表的迭代器    
  13. template<class T, class Ref, class Ptr>    
  14. class List_iterator    
  15. {    
  16. public:    
  17.     List_node<T> *node;    
  18.     void Incr() { node = node->next; }    
  19.     void Decr() { node = node->prev; }    
  20. public:    
  21.     typedef T value_type;    
  22.     typedef Ptr pointer;    
  23.     typedef Ref reference;    
  24.     typedef size_t                     size_type;    
  25.     typedef ptrdiff_t                  difference_type;    
  26.     typedef Bidirectional_iterator_tag iterator_category;         //迭代器的类型是双向的  
  27.     
  28.     typedef List_iterator<T, T&, T*>             iterator;        //迭代器    
  29.     typedef List_iterator<T, const T&, const T*> const_iterator;    
  30.     typedef List_iterator<T, Ref, Ptr>           self;    
  31.         
  32.     List_iterator(List_node<T>* x): node(x) {}     //接受链表结点的构造函数,很管用    
  33.     List_iterator() {}    
  34.     reference operator*() const { return node->data; }                        //解引用重载    
  35.     pointer operator->() const { return &(operator*()); }                     //箭头重载    
  36.     self& operator++() { this->Incr(); return *this; }                        //前增重载    
  37.     self operator++(int) { self tmp = *thisthis->Incr(); return tmp; }      //后增重载    
  38.     self& operator--() { this->Decr(); return *this; }                        //前减重载    
  39.     self operator--(int) { self tmp = *thisthis->Decr(); return tmp; }      //后减重载    
  40.     bool operator==(const List_iterator& x) const { return node == x.node; }  //相等重载    
  41.     bool operator!=(const List_iterator& x) const { return node != x.node; }  //不相等重载    
  42. };    
  1. //List.h  
  2. #pragma once   
  3. #include "List_iterator.h"  
  4.   
  5. //资源分配器    
  6. class MyAlloc    
  7. {    
  8. };    
  9. //链表定义    
  10. template <class T, class Alloc = MyAlloc >    
  11. class List {    
  12. public:          
  13.     typedef List_node<T> list_node; //结点类型    
  14.     typedef list_node* list_type;   //结点指针    
  15.     
  16.     typedef T value_type;    
  17.     typedef value_type* pointer;    
  18.     typedef const value_type* const_pointer;    
  19.     typedef value_type& reference;    
  20.     typedef const value_type& const_reference;    
  21.     typedef size_t size_type;    
  22.     typedef ptrdiff_t difference_type;    
  23.     
  24.     typedef List_iterator<T, T&, T*>             iterator; //迭代器    
  25.     typedef List_iterator<T, const T&, const T*> const_iterator;    
  26. public:    
  27.     List() { node = get_node(); node->next = node; node->prev = node; } //构造哨兵结点    
  28.     ~List() { clear(); }      
  29.     //返回类型要求是iterator,而实际返回的是结点指针,为什么可以呢?关键在于List_iterator有一个接受结点指针的构造函数    
  30.     iterator begin()             { return node->next; }     
  31.     const_iterator begin() const { return node->next; }    
  32.     iterator end()               { return node; }    
  33.     const_iterator end() const   { return node; }    
  34.     bool empty() const { return node->next == node; }    
  35.     reference front() { return *begin(); }    
  36.     const_reference front() const { return *begin(); }    
  37.     reference back() { return *(--end()); }    
  38.     const_reference back() const { return *(--end()); }    
  39.     void push_front(const T& x) { insert(begin(), x); }    
  40.     void push_back(const T& x) { insert(end(), x); }    
  41.     void pop_front() { erase(begin()); }    
  42.     void pop_back() {  iterator tmp = end(); erase(--tmp); }    
  43.     //插入结点    
  44.     void insert(iterator pos, const T &x) {                
  45.         list_type tmp = get_node();    
  46.         tmp->data = x;    
  47.         tmp->next = pos.node;     
  48.         tmp->prev = pos.node->prev;    
  49.         (pos.node->prev)->next = tmp;    
  50.         pos.node->prev = tmp;    
  51.     }    
  52.     //删除结点    
  53.     iterator erase(iterator pos) {     
  54.         list_type next_node = pos.node->next;    
  55.         list_type prev_node = pos.node->prev;    
  56.         prev_node->next = next_node;    
  57.         next_node->prev = prev_node;    
  58.         put_node(pos.node);    
  59.         return next_node;    
  60.     }    
  61.     //清除所有结点    
  62.     void clear() {    
  63.         list_type cur = node->next;    
  64.         while(cur != node)    
  65.         {    
  66.             list_type tmp = cur;    
  67.             cur = cur->next;    
  68.             put_node(tmp);    
  69.         }    
  70.         node->next = node;    
  71.         node->prev = node;    
  72.     }    
  73. private:    
  74.     list_type node;    
  75.     list_type get_node() { return new list_node; }      //分配空间    
  76.     void put_node(list_type p) { delete p; p = NULL; }  //释放空间    
  77. };   
            再来给出函数对象的定义,可以看到绑定器,取反器的具体实现。

  1. //Functional.h  
  2. #pragma once   
  3.   
  4. //用来定义一元操作的参数类别和返回值类别    
  5. template <class Arg, class Result>    
  6. struct unary_function {    
  7.     typedef Arg argument_type;  //内嵌型别技术    
  8.     typedef Result result_type;    
  9. };    
  10. //用来定义二元操作的参数类别和返回值类别    
  11. template <class Arg1, class Arg2, class Result>    
  12. struct binary_function {    
  13.     typedef Arg1 first_argument_type;    
  14.     typedef Arg2 second_argument_type;    
  15.     typedef Result result_type;    
  16. };    
  17.     
  18. //一元操作,就两个    
  19. template <class T>    
  20. struct negate : public unary_function<T, T> {    
  21.     T operator()(const T& x) const { return -x; }    
  22. };    
  23. template <class T>    
  24. struct logical_not : public unary_function<T,bool> {    
  25.     bool operator()(const T& x) const { return !x; }    
  26. };    
  27. //加减乘除取模    
  28. template <class T>    
  29. struct plus : public binary_function<T, T, T> {    
  30.     T operator()(const T& x, const T& y) const { return x + y; }    
  31. };    
  32. template <class T>    
  33. struct minus : public binary_function<T, T, T> {    
  34.     T operator()(const T& x, const T& y) const { return x - y; }    
  35. };    
  36. template <class T>    
  37. struct multiplies : public binary_function<T, T , T> {    
  38.     T operator()(const T& x, const T& y) const { return x * y; }    
  39. };    
  40. template <class T>    
  41. struct divides : public binary_function<T ,T, T> {    
  42.     T operator()(const T& x, const T& y) const { return x / y; }    
  43. };    
  44. template <class T>    
  45. struct modulus : public binary_function<T, T, T> {    
  46.     T operator()(const T& x, const T& y) const { return x % y; }    
  47. };    
  48. //关系运算    
  49. template <class T>    
  50. struct equal_to : public binary_function<T, T, bool> {    
  51.     bool operator()(const T& x, const T& y) const { return x == y; }    
  52. };    
  53. template <class T>    
  54. struct not_equal_to : public binary_function<T, T,bool> {    
  55.     bool operator()(const T& x, const T& y) const { return x != y; }    
  56. };    
  57. template <class T>    
  58. struct greater : public binary_function<T, T, bool> {    
  59.     bool operator()(const T& x, const T& y) const { return x > y; }    
  60. };    
  61. template <class T>    
  62. struct less : public binary_function<T, T, bool> {    
  63.     bool operator()(const T& x, const T& y) const { return x < y; }    
  64. };    
  65. template <class T>    
  66. struct greater_equal : public binary_function<T, T, bool> {    
  67.     bool operator()(const T& x, const T& y) const { return x >= y; }    
  68. };    
  69. template <class T>    
  70. struct less_equal : public binary_function<T, T, bool> {    
  71.     bool operator()(const T& x, const T& y) const { return x <= y; }    
  72. };    
  73. //逻辑运算    
  74. template <class T>    
  75. struct logical_and : public binary_function<T, T, bool>{    
  76.     bool operator()(const T& x, const T& y) const { return x && y; }    
  77. };    
  78. template <class T>    
  79. struct logical_or : public binary_function<T, T, bool>    
  80. {    
  81.   bool operator()(const T& x, const T& y) const { return x || y; }    
  82. };    
  83.   
  84. //绑定第一个参数    
  85. template <class Operation>     
  86. class binder1st: public unary_function<typename Operation::second_argument_type, typename Operation::result_type> {    
  87. public:    
  88.     binder1st(const Operation& x, const typename Operation::first_argument_type& y) : op(x), value(y) {} //构造函数    
  89.     typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const {    
  90.         return op(value, x);  //固定第一个参数    
  91.     }    
  92. protected:    
  93.     Operation op;    
  94.     typename Operation::first_argument_type value;    
  95. };    
  96. //绑定第二个参数    
  97. template <class Operation>     
  98. class binder2nd: public unary_function<typename Operation::first_argument_type,typename Operation::result_type> {    
  99. public:    
  100.     binder2nd(const Operation& x, const typename Operation::second_argument_type& y) : op(x), value(y) {}    
  101.     typename Operation::result_type operator()(const typename Operation::first_argument_type& x) const {    
  102.         return op(x, value);  //固定第二个参数    
  103.     }    
  104. protected:    
  105.     Operation op;    
  106.     typename Operation::second_argument_type value;    
  107. };    
  108. //外部接口    
  109. template <class Operation, class T>    
  110. inline binder1st<Operation> bind1st(const Operation& fn, const T& x) {    
  111.     typedef typename Operation::first_argument_type Arg1_type;    
  112.     return binder1st<Operation>(fn,Arg1_type(x));    
  113. }    
  114. //外部接口    
  115. template <class Operation, class T>    
  116. inline binder2nd<Operation> bind2nd(const Operation& fn, const T& x) {    
  117.     typedef typename Operation::second_argument_type Arg2_type;    
  118.     return binder2nd<Operation>(fn, Arg2_type(x));    
  119. }    
  120.   
  121. //一元操作求反    
  122. template <class Predicate>    
  123. class unary_negate: public unary_function<typename Predicate::argument_type, bool> {    
  124. protected:    
  125.     Predicate pred;    
  126. public:    
  127.     explicit unary_negate(const Predicate& x) : pred(x) {}    
  128.     bool operator()(const typename Predicate::argument_type& x) const {    
  129.     return !pred(x);    
  130.   }    
  131. };    
  132. //二元操作求反    
  133. template <class Predicate>     
  134. class binary_negate : public binary_function<typename Predicate::first_argument_type, typename Predicate::second_argument_type,bool> {    
  135. protected:    
  136.     Predicate pred;    
  137. public:    
  138.     explicit binary_negate(const Predicate& x) : pred(x) {}    
  139.     bool operator()(const typename Predicate::first_argument_type& x, const typename Predicate::second_argument_type& y) const {    
  140.         return !pred(x, y);     
  141.     }    
  142. };    
  143. //外部接口    
  144. template <class Predicate>    
  145. inline unary_negate<Predicate> not1(const Predicate& pred)    
  146. {    
  147.     return unary_negate<Predicate>(pred);    
  148. }    
  149. //外部接口    
  150. template <class Predicate>    
  151. inline binary_negate<Predicate> not2(const Predicate& pred)    
  152. {    
  153.     return binary_negate<Predicate>(pred);    
  154. }    
        最后给出算法的定义。可以看到STL的精髓在于算法与容器的分开设计,通过迭代器将两者粘合在一起,实在是精妙之极。
  1. //Algorithm.h  
  2. #pragma once   
  3.   
  4. //交换两个迭代器所指的元素    
  5. template <class InputIterator1, class InputIterator2>    
  6. inline void Iter_swap(InputIterator1 a, InputIterator2 b) {    
  7.    _Iter_swap(a, b, VALUE_TYPE(InputIterator1)); //VALUE_TYPE返回迭代器的值类型    
  8. }    
  9.   
  10. //真正的交换函数    
  11. template <class InputIterator1, class InputIterator2, class T>    
  12. inline void _Iter_swap(InputIterator1 a, InputIterator2 b, T) {    
  13.    T tmp = *a;    
  14.    *a = *b;    
  15.    *b = tmp;    
  16. }  
  17.   
  18. //条件计数  
  19. template <class InputIterator, class Predicate, class Size>    
  20. void Count_if(InputIterator first, InputIterator last, Predicate pred, Size& n) {    
  21.     for ( ; first != last; ++first)    
  22.         if (pred(*first))    
  23.             ++n;    
  24. }    
  25. //条件计数,有返回值  
  26. template <class InputIterator, class Predicate>    
  27. typename Iterator_traits<InputIterator>::difference_type Count_if(InputIterator first, InputIterator last, Predicate pred) {    
  28.     typename Iterator_traits<InputIterator>::difference_type n = 0;    
  29.     for ( ; first != last; ++first)    
  30.         if (pred(*first))    
  31.             ++n;    
  32.     return n;    
  33. }  

       本人享有博客文章的版权,转载请标明出处 http://blog.csdn.net/wuzhekai1985

相关文章推荐

C++技术点积累(7)——STL之容器汇总

C++技术点积累(7)——STL(标准模板库): STL的从广义上讲分为三类:algorithm(算法)、container(容器)和iterator(迭代器),容器和算法通过迭代器可以进行无缝地连接...

C++ STL入门教程(7)——multimap(一对多索引),multiset(多元集合)的使用(附完整程序代码)

一、Multimap(一对多索引) C++ Multimap和map说支持是操作相同(除了multimap不支持下标运算),但是Multimap允许重复的元素。 begin() 返回指向第...

STL运用的C++技术(4)——重载函数

STL是C++标准库的重要组成部分之一,它不仅是一个可复用的组件库,更是一个包含算法与数据结构的软件框架,同时也是C++泛型编程的很好例子。STL中运用了许多C++的高级技术。本文介绍重载函数。主要参...

STL运用的C++技术(1)——成员模板

STL是C++标准库的重要组成部分之一,它不仅是一个可复用的组件库,更是一个包含算法与数据结构的软件框架,同时也是C++泛型编程的很好例子。STL中运用了许多C++的高级技术。本文...

STL运用的C++技术(5)——重载操作符

STL是C++标准库的重要组成部分之一,它不仅是一个可复用的组件库,更是一个包含算法与数据结构的软件框架,同时也是C++泛型编程的很好例子。STL中运用了许多C++的高级技术。本文介绍重载操作符。主要...

STL运用的C++技术(2)——模板特化

STL是C++标准库的重要组成部分之一,它不仅是一个可复用的组件库,更是一个包含算法与数据结构的软件框架,同时也是C++泛型编程的很好例子。STL中运用了许多C++的高级技术。本文介绍了如下技术:模板...

《C++ STL开发技术导引》全书代码。

  • 2009年03月07日 21:40
  • 18.44MB
  • 下载

C++总结7——STL基本原理和用法

1.STL的三种类型容器 顺序容器:vector 向量容器 deque 双端队列 list 链表 容器适配器:st...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:STL运用的C++技术(7)——代码整合
举报原因:
原因补充:

(最多只允许输入30个字)