(原創) iterator到底是不是pointer? (C/C++) (STL)

Abstract
使用iterator時,能使用pointer的*、++、--與->等操作,到底iterator是不是pointer呢?

Introduction
一個很典型使用vector的STL程式碼。

1  #include < vector >
2  #include < iostream >
3 
4  using   namespace std;
5 
6  int main() {
7    vector < int > ivec;
8    ivec.push_back( 1 );
9    ivec.push_back( 2 );
10    ivec.push_back( 3 );
11    ivec.push_back( 4 );
12   
13    for (vector < int > ::iterator iter = ivec.begin(); iter != ivec.end(); ++ iter)
14      cout <<   * iter << endl;
15  }


執行結果

1
2
3
4


13行

1  for (vector < int > ::iterator iter = ivec.begin(); iter != ivec.end(); ++ iter)
2    cout <<   * iter << endl;


iterator有兩個很神奇的操作:++iter與*iter,怎麼看都像在操作pointer,那到底iterator是不是pointer呢?

學C++的人大概分兩種背景的族群:
1.原來會C,有pointer概念

看到iterator的*、++、--與->等操作,一定會認為iterator就是個pointer,但我翻遍了C++ Primer 4th,就是沒看到它肯定地說『iterator就是poiner』,或說『iterator不是pointer』,留下一個曖昧的想像空間。若以C語言思考,iterator『應該』是pointer。

2.原來會C#、Java,有OO概念
『Everthing is object』,int是object,vector是object,所所以iterator『應該』也是object,但是iterator為什麼能用*、++、--與->等操作呢?那只是因為operator overloading的原因。況且C++對於pointer幾乎都有新的解決方案,如reference取代pass by pointer、vector取代array、string取代char *、STL containter取代dynamic alloction..等(請參閱(原創) C/C++哪些地方會用到pointer呢? (C/C++) (C))。 若以OO思維思考,iterator『應該』不是pointer。

到底誰說的才對呢?所謂『有code有真相』,我們直接拿SGI STL的source code來看看最常用的vector與list的iterator是如何實現。(我並沒有包含完整的SGI STL source,只截取我要解釋的部分來說明)。

stl_vector.h / C++

1  template < class T >
2  class vector {
3  public :
4    typedef T value_type;
5    typedef value_type * iterator; // pointer to T
6  }


5行

typedef value_type * iterator; // pointer to T


這裡很明顯,vector的iterator就是個pointer,看你T是什麼型別,就是指向T的pointer,所以對vector的iterator來說,它完全是一個pointer。 C語言背景的pointer概念在vector是正確的。

stl_list.h / C++

1  template < class T >
2  struct __list_node {
3    __list_node < T >   * void_pointer;
4    void_pointer prev;
5    void_pointer next;
6    T data;
7  };
8   
9  template < class T, class Ref, class Ptr >
10  struct __list_iterator {
11    typedef Ref reference;
12    typedef Ptr pointer;
13    typedef __list_iterator < T, Ref, Ptr > self;
14    typedef __list_node < T >   * link_type;
15    link_type node; // pointer to node
16   
17    reference operator * () const {
18      return ( * node).data;
19    }
20   
21    pointer operator -> () const {
22      return   & ( operator * ());
23    }
24   
25    self &   operator ++ () {
26      node = (link_type)(( * node).next);
27      return   * this ;
28    }
29   
30    self operator -- () {
31      node = (link_type)(( * node).prev);
32      return   * this ;
33    }
34  };
35 
36  template < class T >
37  class list {
38  public :     
39  typedef __list_iterator < T, T & , T *>   iterator;
40  };


39行

typedef __list_iterator < T, T & , T *>   iterator;


list的iterator是__list_iterator的typedef,所以要繼續追__list_iterator是什麼東西。

9行

template < class T, class Ref, class Ptr >
struct __list_iterator {
  typedef Ref reference;
  typedef Ptr pointer;
  typedef __list_iterator
< T, Ref, Ptr > self;
  typedef __list_node
< T >   * link_type;
  link_type node;
// pointer to node
 
  reference
operator * () const {
   
return ( * node).data;
  }
 
  pointer
operator -> () const {
   
return   & ( operator * ());
  }
 
  self
&   operator ++ () {
    node
= (link_type)(( * node).next);
   
return   * this ;
  }
 
  self
operator -- () {
    node
= (link_type)(( * node).prev);
   
return   * this ;
  }
};


__list_iterator是定義list iterator的class, 所以OO背景說的沒錯,iterator不是pointer,它只是一個object,iterator的*、->、++、--都是operator overloading做出來的,而不是pointer本身的操作。 在++與--中,我們看到了node,node是什麼東西呢?繼續追下去...

14行

typedef __list_node < T >   * link_type;
link_type node;
// pointer to node


我們知道list其實是資料結構的double linked list,由node所構成, 所以iterator的所有操作,本質上都是在操作node,再來看__list_node是如何定義的。

2行

template < class T >
struct __list_node {
  __list_node
< T >   * void_pointer;
  void_pointer prev;
  void_pointer next;
  T data;
};


__list_node利用prev與next指向前一個node與後一個node,prev和next都是pointer,是個指向__list_node<T>的pointer,所以__list_iterator的++、--最後是靠pointer沒錯,不過list的iterator本身並不是pointer,而是個object,只是它用operator overloading模擬了pointer的操作而已。

Conclusion
iterator是不是pointer呢?要看container而定,由上可知,vector的iterator是pointer,list的iterator就不是pointer,而是object利用operator overloading使它表面上的操作像pointer而已,但並不是一個pointer。所以C語言背景與OO背景的人都是瞎子摸象,只摸到iterator的一部分。iterator除了因為vector因為較簡單,所以使用native pointer外,其他container的interator都是一種smart pointer,因為其操作跟pointer一樣,你可以將它當成pointer方式使用,不過他仍然不是pointer

iterator是泛型編程一個重要的概念,container只需知道如何使用iterator(*、++、--、->)即可,完全不需知道iterator的實際型別,而演算法可以完全獨立於container與iterator自行發展,只要設計時以iterator為對外interface即可。

See Also
(原創) C/C++哪些地方會用到pointer呢? (C/C++) (C)

Reference
侯捷 2002,STL源碼剖析,碁峰出版社
葉至軍 2007,C++ STL開發技術導引,人民郵電出版社

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值