关闭

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

173人阅读 评论(0) 收藏 举报
分类:

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

       重载操作符是具有特殊名称的函数:保留了operator后接需定义的操作符符号。这是《C++ Primer》中的定义。在STL中重载操作符主要用在两个地方,一个是迭代器中,另一个是算法中。本文介绍在迭代器中的应用,下篇介绍在算法中的应用。在本系列博文中,多次提到迭代器,不愧是STL的关键所在。迭代器就像是各种容器对象的智能指针,这仅仅是我的理解。指针的各种行为中常见的有解引用操作符(*)、箭头操作符(->)、自增、自减等。对于容器来说,必须重载这些操作符,以适应自身的指针行为。重载这些操作符,迭代器责无旁贷。看一段STL的源码,做了些修改,更清楚一些。

  1. //结点定义,双向链表  
  2. template <class T>  
  3. struct List_node {  
  4.     List_node* next;  
  5.     List_node* prev;  
  6.     T data;  
  7. };  
  8. //链表的迭代器  
  9. template<class T, class Ref, class Ptr>  
  10. class List_iterator  
  11. {  
  12. public:  
  13.     List_node<T> *node;  
  14.     void Incr() { node = node->next; }  
  15.     void Decr() { node = node->prev; }  
  16. public:  
  17.     typedef T value_type;  
  18.     typedef Ptr pointer;  
  19.     typedef Ref reference;  
  20.     typedef size_t                     size_type;  
  21.     typedef ptrdiff_t                  difference_type;  
  22.     typedef bidirectional_iterator_tag iterator_category;  
  23.   
  24.     typedef List_iterator<T, T&, T*>             iterator;        //迭代器  
  25.     typedef List_iterator<T, const T&, const T*> const_iterator;  
  26.     typedef List_iterator<T, Ref, Ptr>           self;  
  27.       
  28.     List_iterator(List_node<T>* x): node(x) {}     //接受链表结点的构造函数,很管用  
  29.     List_iterator() {}  
  30.     reference operator*() const { return node->data; }                        //解引用重载  
  31.     pointer operator->() const { return &(operator*()); }                     //箭头重载  
  32.     self& operator++() { this->Incr(); return *this; }                        //前增重载  
  33.     self operator++(int) { self tmp = *thisthis->Incr(); return tmp; }      //后增重载  
  34.     self& operator--() { this->Decr(); return *this; }                        //前减重载  
  35.     self operator--(int) { self tmp = *thisthis->Decr(); return tmp; }      //后减重载  
  36.     bool operator==(const List_iterator& x) const { return node == x.node; }  //相等重载  
  37.     bool operator!=(const List_iterator& x) const { return node != x.node; }  //不相等重载  
  38. };  

      上面这段代码展现了这些操作符是如何被重载。其实这是个双向链表的迭代器定义,有自增和自减。再进一步,那么链表如何使用上述定义的迭代器呢?下面给出链表的定义,只取STL链表的部分功能,同时给出了测试用例。已在VS2008下测试通过。

  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. //结点定义,双向链表,把上面的代码拷贝下来即可  
  5. //链表的迭代器,把上面的代码拷贝下来即可  
  6.   
  7. //资源分配器  
  8. class MyAlloc  
  9. {  
  10. };  
  11. //链表定义  
  12. template <class T, class Alloc = MyAlloc >  
  13. class List {  
  14. public:        
  15.     typedef List_node<T> list_node; //结点类型  
  16.     typedef list_node* list_type;   //结点指针  
  17.   
  18.     typedef T value_type;  
  19.     typedef value_type* pointer;  
  20.     typedef const value_type* const_pointer;  
  21.     typedef value_type& reference;  
  22.     typedef const value_type& const_reference;  
  23.     typedef size_t size_type;  
  24.     typedef ptrdiff_t difference_type;  
  25.   
  26.     typedef List_iterator<T, T&, T*>             iterator; //迭代器  
  27.     typedef List_iterator<T, const T&, const T*> const_iterator;  
  28. public:  
  29.     List() { node = get_node(); node->next = node; node->prev = node; } //构造哨兵结点  
  30.     ~List() { clear(); }    
  31.     //返回类型要求是iterator,而实际返回的是结点指针,为什么可以呢?关键在于List_iterator有一个接受结点指针的构造函数  
  32.     iterator begin()             { return node->next; }   
  33.     const_iterator begin() const { return node->next; }  
  34.     iterator end()               { return node; }  
  35.     const_iterator end() const   { return node; }  
  36.     bool empty() const { return node->next == node; }  
  37.     reference front() { return *begin(); }  
  38.     const_reference front() const { return *begin(); }  
  39.     reference back() { return *(--end()); }  
  40.     const_reference back() const { return *(--end()); }  
  41.     void push_front(const T& x) { insert(begin(), x); }  
  42.     void push_back(const T& x) { insert(end(), x); }  
  43.     void pop_front() { erase(begin()); }  
  44.     void pop_back() {  iterator tmp = end(); erase(--tmp); }  
  45.     //插入结点  
  46.     void insert(iterator pos, const T &x) {              
  47.         list_type tmp = get_node();  
  48.         tmp->data = x;  
  49.         tmp->next = pos.node;   
  50.         tmp->prev = pos.node->prev;  
  51.         (pos.node->prev)->next = tmp;  
  52.         pos.node->prev = tmp;  
  53.     }  
  54.     //删除结点  
  55.     iterator erase(iterator pos) {   
  56.         list_type next_node = pos.node->next;  
  57.         list_type prev_node = pos.node->prev;  
  58.         prev_node->next = next_node;  
  59.         next_node->prev = prev_node;  
  60.         put_node(pos.node);  
  61.         return next_node;  
  62.     }  
  63.     //清除所有结点  
  64.     void clear() {  
  65.         list_type cur = node->next;  
  66.         while(cur != node)  
  67.         {  
  68.             list_type tmp = cur;  
  69.             cur = cur->next;  
  70.             put_node(tmp);  
  71.         }  
  72.         node->next = node;  
  73.         node->prev = node;  
  74.     }  
  75. private:  
  76.     list_type node;  
  77.     list_type get_node() { return new list_node; }      //分配空间  
  78.     void put_node(list_type p) { delete p; p = NULL; }  //释放空间  
  79. };  
  80. //测试用例  
  81. int main()  
  82. {  
  83.     List<int> l;  
  84.     l.push_back(1);  
  85.     l.push_back(2);  
  86.     cout<<l.front()<<' '<<l.back()<<endl; //1 2  
  87.     l.push_front(3);  
  88.     l.push_front(4);  
  89.     cout<<l.front()<<' '<<l.back()<<endl; //4 2  
  90.     l.pop_back();  
  91.     l.pop_front();  
  92.     cout<<l.front()<<' '<<l.back()<<endl; //3 1    
  93.     cout<<l.empty()<<endl;  //0  
  94.     l.clear();  
  95.     cout<<l.empty()<<endl;  //1  
  96.     return 0;  
  97. }  

       上面这两段程序已经给出了链表的部分功能,同时看到了迭代器的运用以及重载操作符的实现。搞清楚了以上代码,再去看STL的源代码,可能会轻松一点吧,大同小异,核心的结构基本上都是这样的。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:34827次
    • 积分:788
    • 等级:
    • 排名:千里之外
    • 原创:26篇
    • 转载:116篇
    • 译文:1篇
    • 评论:6条
    最新评论