C++STL迭代器iterator设计

本文深入探讨了C++中的迭代器,将其比作智能指针,展示了如何使用迭代器访问容器元素。迭代器分为输入迭代器、输出迭代器、前向迭代器、双向迭代器和随机访问迭代器五类,并详细解释了它们的特性和使用场景。此外,文章还讨论了迭代器的distance函数和traits编程技术,用于获取迭代器的关联类型。最后,介绍了如何确保新设计的迭代器与STL兼容的方法。
摘要由CSDN通过智能技术生成


前言

迭代器是一种抽象的设计概念,现实设计语言中并没有直接对应于这个概念的实物。
iterator模式定义:提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无需暴露该聚合物的内部表达方式。


迭代器是一种smart pointer

vector<int>::iterator
list<int>::iterator
deque<int>::iterator

auto_ptr

void func()
{
    auto_ptr<string> ps(new string("jjhou));
    cout << *ps << endl;
    cout << ps->size() << endl;
    // 离开前不需要delete
}

迭代器是对象,它需要重载operator*和operator->

// file: 3autoptr.cpp
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;
};

// file: 3mylist.h
template<typename T>
class List
{
private:
    void insert_front(T value);
    void insert_end(T value);
    void display(std::ostream &os = std::cout) const;
    // ...
private:
    ListItem<T>* _end;
    ListItem<T>* _front;
    long _size;
};
template<typename T>
class ListItem
{
public:
    T value() const {return _value;}
    ListItem* next() const {return _next;}
    ...
private:
    T _value;
    ListItem* _next;
};

// file : 3mylist-iter.h
#include "3mylist.h"
template<class Item>
struct ListIter
{
Item* ptr;
ListIter(Item* p = 0):ptr(p) {}

}; 

迭代器相应型别associated types

利用template参数推到机制获得迭代器所指对象的类型

template<class I, class T>
void func_impl(I iter, T t)
{
    T tmp;
    //...
}
template<class I>
inline void func(I iter)
{
    func_impl(iter, *iter);
}
int main()
{
    int i;
    func(&i);
}

traits编程技法

迭代器所指对象的型别称为该迭代器的value type。
模板参数推导机制只能推导参数,无法推导函数的返回值类型。

template<class T>
struct MyIter
{
    typedef T value_type;
    T* ptr;
    MyIter(T* p=0) : ptr(p) { }
    T& operator*() const { return *ptr; }
    // ...
};
template<class I>
//若I不是class则该方法失效,需要特例化该模板
typename iterator_traits<I>::value_type func(I ite)
// typename ::value_type func(I ite)
    { return *ite; }
// ...
MyIter<int> ite(new int(4));
cout << func(ite) << endl;

//特例化

//下面这个class template专门用来“萃取”迭代器的特性,而value type正是其一
template<class I>
struct iterator_traits     //traits意味“特性”
{
    typedef typename I::value_type value_type;
};
template<class T>
struct iterator_traits<T*> //特例化——迭代器是个原生指针
{
    typedef T value_type;
};
//特例化版——当迭代器是个pointer-to-const时,萃取的是T,而非const T
template<class T>
struct iterator_traits<const T*> 
                                  
{
    typedef T value_type;
};
template<>
struct iterator_traits<double>
{
    typedef int value_type;
};

traits

//常用的迭代器相应型别
template<class I>
struct iterator_traits{
    typedef typename I::iterator_category  iterator_category;
    // 迭代器所指对象的类型
    typedef typename I::value_type         value_type;
    // 表示两个迭代器之间的距离
    typedef typename I::difference_type    difference_type;
    // pointer type
    typedef typename I::pointer            pointer;
    // reference type
    typedef typename I::reference          reference;
};
// iterator_traits必须针对传入的pointer及pointer-to-const,设计特例化版本



// C++内建的ptrdiff_t定义于<cstddef>作为原生指针的difference type
template<class T>
struct iterator_traits<T*>{
    typedef ptrdiff_t defference_type;
    typedef T* pointer;
    typedef T& reference;
};
template<class T>
struct iterator_traits<const T*>{
    typedef ptrdiff_t defference_type;
    typedef const T* pointer;
    typedef const T& reference;
};

Item& operator*() const {return *ptr;}
Item* operator->() const {return ptr;}
Item&为 ListIter的reference type,而Item*为其pointer type

迭代器分类

根据移动特性与施行操作,迭代器被分为五类:

  • input iterator:这种迭代器所指的对象,不允许外界改变。只读
  • output iterator:只写
  • forward iterator:允许“写入型”算法如replace在此中迭代器所形成的区间上进行读写操作
  • bidirectional iterator:可双向移动
  • random access iterator:涵盖所有指针算术能力,p+n, p-n, p[n], p1-p2, p1<p2
// 五个作为编辑用的类型 tag types
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};

distance

template<class InputIterator>
inline iterator_traits<InputIterator>::defference_type
__distance(InputIterator first, InputIterator last, input_iterator_tag)
{
    iterator_traits<InputIterator>::defference_type n = 0;
    while (first != last){
        ++first; ++n;
    }
    return n;
}
template<class RandomAccessIterator>
inline iterator_traits<RandomAccessIterator>::difference_type
__distance(RandomAccessIterator first, RandomAccessIterator last, random_access_iterator_tag)
{
    return last - first;
}
template<class InputIterator>
inline iterator_traits<InputIterator>::difference_type
distance(InputIterator first, InputIterator last)
{
    typedef typename iterator_traits<InputIterator>::iterator_category category;
    return __distance(first, last, category());
}

在这里插入图片描述

std::iterator

每个新设计的迭代器都应该继承下面的类,以保证与STL兼容

template<class Category,
         class T,
         class Distance = ptrdiff_t,
         class Pointer = T*,
         class Reference = T&>
struct iterator{
    typedef Category   iterator_category;
    typedef T          value_type;
    typedef Distance   difference_type;
    typedef Pointer    pointer;
    typedef Reference  reference;
};

新定义的迭代器应该有如下形式

template<class Item>
struct ListIter: public std::iterator<std::forward_iterator_tag, Item>

总结
在这里插入图片描述

iterator源代码完整重列

<stl_iterator.h>

SIG STL __type_traits

struct __true_type {};
struct __false_type {};
// 泛化版本
template<class type>
struct __type_traits
{
    typedef __true_type this_dummy_member_must_be_first;
    /*   */
    typedef __false_type  has_trivial_default_constructor;
    typedef __false_type  has_trivial_copy_constructor;
    typedef __false_type  has_trivial_assignment_constructor;
    typedef __false_type  has_trivial_destructor;
    typedef __false_type  is_POD_type;
};
// 自行设计一个__type_traits特例化版本
template<> struct __type_traits<自定义的类>
{
    typedef __true_type  has_trivial_default_constructor;
    typedef __true_type  has_trivial_copy_constructor;
    typedef __true_type  has_trivial_assignment_constructor;
    typedef __true_type  has_trivial_destructor;
    typedef __true_type  is_POD_type;
};

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值