第三章 迭代器(iterators)概念与traits编程技法

迭代器(iterators)是一种抽象的设计概念,其中iterator模式定义如下:提供一种方法,使之能够依序巡访某个聚合物(容器)所含的各个元素,而又无需暴露该聚合物的内部表述方式。

3.1 迭代器设计思想——STL关键所在

  1. 不论是泛型思维或STL的实际运用,迭代器(iterators)都扮演着重要的角色。
  2. STL的中心思想在于:将数据容器(containers)和算法(algorithms)分开,彼此
    独立设计,最后再以帖胶着剂将它们撮合在起。
  3. 容器和算法的泛型化,从技术角度来看并不困难,C++的class templates和function templates可分别达成目标。如何设计出两者之间的良好胶着剂,才是大难题。
    以下是容器、算法、迭代器(iterator,扮演粘胶角色)的合作展示。以算法find()为例,它接受两个迭代器和个“搜寻目标":
//来自SGI <stl_algo.h> 
template <class InputIterator,class T>
InputIterator find(InputIterator first,InputIterator last,const T& value){
   
    while(first != last && *fist != value)
        ++first;
    return first;
}

只要给予不同的迭代器,find()便能够对不同的容器进行查找操作:

#include <iostream>
#include<vector>
#include<list>
#include<deque>
#include<algorithm>
using namespace std;

int main()
{
   
    const int arraySize = 7;
    int ia[arraySize] = {
   0,1,2,3,4,5,6};

    vector<int> ivect(ia,ia+arraySize);
    list<int> ilist(ia,ia+arraySize);
    deque<int> ideque(ia,ia+arraySize);

    vector<int>::iterator it1 = find(ivect.begin(),ivect.end(),4);
    if(it1 == ivect.end())
        cout<<"4 not found."<<endl;
    else
        cout<<"4 found."<<*it1<<endl;

    list<int>::iterator it2 = find(ilist.begin(),ilist.end(),6);
    if(it2 == ilist.end())
        cout<<"6 not found."<<endl;
              else
              cout<<"6 found"<<*it2<<endl;

    deque<int>::iterator it3=find(ideque.begin(),ideque.end(),8);
    if(it3 == ideque.end())
        cout<<"8 not found."<<endl;
    else
        cout<<"8 found."<<*it3<<endl;
}

在这里插入图片描述

3.2 迭代器(iterators)是一种smart pointe

  1. 迭代器是一种行为类似指针的对象,而指针的各种行为中最常见也最重要的便是内容提领(dereference)和成员访问(member access) , 因此, 迭代器最重要的编程工作就是对operator*和operator->进行重载(overloading)工作。
  2. C++标准程序库有一个auto_ptr这是一个用来包装原生指针(native pointer)的对象, 声名狼藉的内存漏洞(memory leak)问题可藉此获得解决。

auto_ptr用法如下, 和原生指针一模一样:

void func()
{
   
    auto_ptr<string> ps(new string("jjhou"));
    cout<<*ps<<endl;//输出:jjhou
    cout<<ps->size()<<endl;//输出:5
    //离开前不需 delete, auto_ptr 会自动释放内存
}

函数第一行的意思是, 以算式new动态配置一个初值为 ''jjhou" 的string对象,并将所得结果(一个原生指针)作为auto_ptr对象的初值。注意, auto_ptr角括号内放的是 “原生指针所指对象” 的型别, 而不是原生指针的型别。

auto_ptr 的源代码在头文件中,auto_ptr的行为如下:

template<class T>
class auto_ptr {
   
public:
explicit auto_ptr(T *p = 0): pointee(p) {
   }
template<class U>
auto_ptr(auto_ptr<U>& rhs): pointee(rhs.release()) {
   }
_auto_ptr() {
    delete pointee; }

template<class U>
auto_ptr<T>& operator=(auto_ptr<U>& rhs) {
   

    if(this !=&rhs) reset(rhs.release());
    return *this;
}
T& operator* () const {
    return *pointee; }
T* operator->()const {
    return pointee; }
T* get() const{
    return pointee;}
//...
private:
T *pointee;
};

有了模仿对象,设计list迭代器,list节点的结构如下:

template <typename T>
class List
{
   
    void insert_front(T value);
    void insert_end(T value);
    void display(std::operator &os = std::cout)const;
    //...
private:
    ListItem<T>* _end;
    ListItem<T>* _front;
    long _size;
};

template<typename T>
class LisItem
{
   
public:
    T value()const {
   return _value;}
    ListItem* next() const {
   return _next;}
    //...
   private:
    T _value;
    ListItem* _next;//单向链表
};
  1. 如何将这个List套用到先前所说的find()呢?我们需要为它设计一个行为类似指针的外衣,也就是个迭代器。
  2. 当我们提领这一迭代器时,传回的应该是个ListItem对象;
  3. 为了让该迭代器适用于任何型态的节点,而不只限于Listrtem, 我们可以将它设计为一个class template:
template <class Item> // Item可以是单向链表节点或双向链表节点。
struct ListIter
{
   
    Item* ptr;
    ListIter(Item* p = 0):ptr(p){
   }//默认构造
    
    //不必实现copy ctor, 因为编译器提供的缺省行为己足够
   //不必实现operator=, 因为编译器提供的缺省行为己足够
    
    Item& operator* () const{
    return *ptr; } 
    Item* operator->() const {
    return ptr; }
   
    
 //(1) pre-increment operator 
Listiter& operator++()
{
   
        ptr = ptr->next (); 
        return *this;
}

   
//(2) post-increment operator 
Listiter operator++(int)
{
    Listiter tmp = *this; 
    ++*this; 
    return tmp;
}

bool operator==(const Listiter& i) const 

{
    
    return ptr == i.ptr;
} 

bool operator !=(const ListIter& i) const
{
    
        return ptr != i.ptr; 
}
        
};

现在我们可以将List和find()藉由Listiter粘合起来:

void main()
{
   
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值