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

转载 2016年05月31日 11:00:05

 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的源代码,可能会轻松一点吧,大同小异,核心的结构基本上都是这样的。

相关文章推荐

运算符重载,迭代器

【1】 bool operator > (const Book &p) const { return p.isbn < isbn; } 是对运算符 > 的重载 ,const Book &p ...

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

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

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

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

c++之STL(9)重载函数调用操作符 函数对象 谓词

重载函数调用操作符 函数对象:定义了调用操作符的类,其对象称为“函数对象” 一元函数对象 一元谓词 二元函数对象 二元谓词 #include // #include #include #inclu...

C++ 中Traits技术 (5) —— 关于STL中对迭代器封装的类型介绍

上一篇讲到traits的类型萃取,可将迭代器相关的类型获取用于变量声明和函数返回等操作。对于原生指针和const指针可以采用偏特化技术进行处理。 在STL中,对迭代器除了封装类型信息以外,还有一些...

C++ trick之重载类型转换操作符 “orthodox”技术

转自: http://sandy-sp.com/blog/article.asp?id=20 C++ trick之重载类型转换操作符C++很强大,许多玩意都可以自定义,比如类型转换操作符。但我这里要扯...

C++ Primer学习笔记——$14 操作符重载、函数对象及类类型转换

题记:本系列学习笔记(C++ Primer学习笔记)主要目的是讨论一些容易被大家忽略或者容易形成错误认识的内容。只适合于有了一定的C++基础的读者(至少学完一本C++教程)。  作者: tyc611,...
  • whycold
  • whycold
  • 2011年01月19日 15:09
  • 730

C++基础——操作符重载

关于操作符重载,是C++一个十分强大的功能。 本文初略介绍下,涉及到友元以及函数重载 头文件MyClass.h: #ifndef MYCLASS_H_ #define MYCLASS_H_ ...
  • mfcing
  • mfcing
  • 2012年03月21日 22:49
  • 604

C++ 面向对象(二)—— 操作符重载

C++ 实现了在类(class)之间使用语言标准操作符,而不只是在基本数据类型之间使用。例如: int a, b, c; a = b + c; 是有效操作,因为加号两边的变量都是基本数据类型。然...

《C++ Primer》学习笔记—— 重载操作符与转换

一,      重载操作符的定义1,不可重载的操作符:::.*? : 2,不能通过连接其他合法符号来创建任何新的操作符。3,不能改变或添加内置类型的操作符。4,操作符的优先级、结合性、操作数数目...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:STL运用的C++技术(5)——重载操作符
举报原因:
原因补充:

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