STL之迭代器

本文详细介绍了迭代器的不同种类及其特性,包括输入迭代器、输出迭代器、前向迭代器、双向迭代器和随机访问迭代器。此外,还深入探讨了迭代器适配器的工作原理,并提供了插入迭代器、反向迭代器及输入输出迭代器的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

根据实现的功能,迭代器分为五类:
迭代器分类
不同种类迭代器可进行的操作(from):

categorypropertiesvalid expressions
all categoriescopy-constructible, copy-assignable and destructibleX b(a);
b = a;
Can be incremented++a
a++
Random AccessBidirectionalForwardInputSupports equality/inequality comparisonsa == b
a != b
Can be dereferenced as an rvalue*a
a->m
OutputCan be dereferenced as an lvalue
(only for mutable iterator types)
*a = t
*a++ = t
default-constructibleX a;
X()
Multi-pass: neither dereferencing nor
incrementing affects dereferenceability
{ b=a; *a++; *b; }
Can be decremented--a
a--
*a--
Supports arithmetic operators + and -a + n
n + a
a - n
a - b
Supports inequality comparisons (<, >, <= and >=)
between iterators
a < b
a > b
a <= b
a >= b
Supports compound assignment operations += and -=a += n
a -= n
Supports offset dereference operator ([])a[n]

迭代器的结构

源码在stl_iterator_base_types.h中。

// 5种迭代器类别
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 {};

// 迭代器基类, 自行开发的迭代器最好继承此基类
template <typename Category, typename T, typename Distance = ptrdiff_t, typename Pointer = T*, typename Reference = T&>
struct iterator
{
    // Category为上面5种类别之一
    typedef Category  iterator_category;
    typedef T         value_type;
    typedef Distance  difference_type;
    typedef Pointer   pointer;
    typedef Reference reference;
};

// 提取出迭代器(模板参数)的内置类型
template <typename Iterator>
struct iterator_traits
{
    typedef typename Iterator::iterator_category iterator_category;
    typedef typename Iterator::value_type        value_type;
    typedef typename Iterator::difference_type  difference_type;
    typedef typename Iterator::pointer            pointer;
    typedef typename Iterator::reference         reference;
};

// 常规指针的偏特化版本
template <typename T>
struct iterator_traits<T*>
{
    typedef random_access_iterator_tag iterator_category;
    typedef T                         value_type;
    typedef ptrdiff_t                 difference_type;
    typedef T*                        pointer;
    typedef T&                        reference;
};

// 常规const指针的偏特化版本
template <class T>
struct iterator_traits<const T*>
{
    typedef random_access_iterator_tag iterator_category;
    typedef T                         value_type;
    typedef ptrdiff_t                 difference_type;
    typedef const T*                  pointer;
    typedef const T&                  reference;
};


// These functions is not a part of the C++ standard but is syntactic sugar for internal library use only
template<typename Iter>
inline typename iterator_traits<Iter>::iterator_category
__iterator_category(const Iter&)
{
    return typename iterator_traits<Iter>::iterator_category();
}

template <class Iter>
inline typename iterator_traits<Iter>::difference_type*
__distance_type(const Iter&)
{
    return static_cast<typename iterator_traits<Iter>::difference_type*>(0);
}

template <class Iter>
inline typename iterator_traits<Iter>::value_type*
__value_type(const Iter&)
{
    return static_cast<typename iterator_traits<Iter>::value_type*>(0);
}

template <class Iter>
inline typename iterator_traits<Iter>::iterator_category
iterator_category(const Iter& i) { return __iterator_category(i); }

template <class Iter>
inline typename iterator_traits<Iter>::difference_type*
distance_type(const Iter& i) { return __distance_type(i); }

template <class Iter>
inline typename iterator_traits<Iter>::value_type*
value_type(const Iter& i) { return __value_type(i); }

几个基本的函数

源码在stl_iterator_base_funcs.h中。

// 计算两个迭代器之间的距离
template <typename InputIterator>
inline typename iterator_traits<InputIterator>::difference_type
__distance(InputIterator first, InputIterator last, input_iterator_tag)
{
    typename iterator_traits<InputIterator>::difference_type n = 0;
    while (first != last)
    {
        ++first;
        ++n;
    }
    return n;
}

template <typename RandomAccessIterator>
inline typename iterator_traits<RandomAccessIterator>::difference_type
__distance(RandomAccessIterator first, RandomAccessIterator last, random_access_iterator_tag)
{
    return last - first;
}

template <typename InputIterator>
inline typename iterator_traits<InputIterator>::difference_type
distance(InputIterator first, InputIterator last)
{
    typedef typename iterator_traits<InputIterator>::iterator_category Category;
    return __distance(first, last, Category());
}

// 前进
template <typename InputIterator, typename Distance>
inline void __advance(InputIterator& i, Distance n, input_iterator_tag)
{
    while (n--) ++i;
}

template <typename BidirectionalIterator, typename Distance>
inline void __advance(BidirectionalIterator& i, Distance n, bidirectional_iterator_tag)
{
    if (n > 0)
        while (n--) ++i;
    else
        while (n++) --i;
}

template <typename RandomAccessIterator, typename Distance>
inline void __advance(RandomAccessIterator& i, Distance n, random_access_iterator_tag)
{
    i += n;
}

template <typename InputIterator, typename Distance>
inline void advance(InputIterator& i, Distance n)
{
    typedef typename iterator_traits<InputIterator>::iterator_category Category;
    __advance(i, n, Category());
}

迭代器适配器

有3种,分别为插入迭代器,反向迭代器,输入输出迭代器。

插入迭代器

做的工作是:将赋值操作改为插入操作。分为back_insert_iterator,front_insert_iterator,insert_iterator三种。insert_iterator不仅进行插入操作,还会进行一个右移操作,这样就可以进行持续的插入。
为了操作方便,还定义了3个函数,他们返回相应的插入迭代器。

template <typename Container>
class back_insert_iterator : public iterator<output_iterator_tag,void,void,void,void>
{
protected:
    Container* container;
public:
    typedef Container container_type;

    explicit back_insert_iterator(Container& x) : container(&x) {}
    back_insert_iterator<Container>&
    operator=(const typename Container::value_type& value)
    {
        container->push_back(value);
        return *this;
    }
    back_insert_iterator<Container>& operator*()
    { return *this; }
    back_insert_iterator<Container>& operator++()
    { return *this; }
    back_insert_iterator<Container>& operator++(int)
    { return *this; }
};

template <typename Container>
inline back_insert_iterator<Container>
back_inserter(Container& x)
{
    return back_insert_iterator<Container>(x);
}

template <typename Container>
class front_insert_iterator : public iterator<output_iterator_tag,void,void,void,void>
{
protected:
    Container* container;
public:
    typedef Container container_type;

    explicit front_insert_iterator(Container& x) : container(&x) {}
    front_insert_iterator<Container>&
    operator=(const typename Container::value_type& value)
    {
        container->push_front(value);
        return *this;
    }
    front_insert_iterator<Container>& operator*()
    { return *this; }
    front_insert_iterator<Container>& operator++()
    { return *this; }
    front_insert_iterator<Container>& operator++(int)
    { return *this; }
};

template <typename Container>
inline front_insert_iterator<Container>
front_inserter(Container& x)
{
    return front_insert_iterator<Container>(x);
}

template <class Container>
class insert_iterator : public iterator<output_iterator_tag,void,void,void,void>
{
protected:
    Container* container;
    typename Container::iterator iter;
public:
    typedef Container container_type;

    insert_iterator(Container& x, typename Container::iterator i)
        : container(&x), iter(i) {}
    insert_iterator<Container>&
    operator=(const typename Container::value_type& value)
    {
        iter = container->insert(iter, value);
        ++iter;
        return *this;
    }
    insert_iterator<Container>& operator*()
    { return *this; }
    insert_iterator<Container>& operator++()
    { return *this; }
    insert_iterator<Container>& operator++(int)
    { return *this; }
};

template <typename Container, typename Iterator>
inline insert_iterator<Container>
inserter(Container& x, Iterator i)
{
    typedef typename Container::iterator iter;
    return insert_iterator<Container>(x, iter(i));
}

反向迭代器

反向迭代器,顾名思义。

template <typename Iterator>
class reverse_iterator
{
protected:
    Iterator current;
public:
    typedef typename iterator_traits<Iterator>::iterator_category
    iterator_category;
    typedef typename iterator_traits<Iterator>::value_type
    value_type;
    typedef typename iterator_traits<Iterator>::difference_type
    difference_type;
    typedef typename iterator_traits<Iterator>::pointer
    pointer;
    typedef typename iterator_traits<Iterator>::reference
    reference;

    typedef Iterator iterator_type;
    typedef reverse_iterator<Iterator> Self;

public:
    reverse_iterator() {}
    explicit reverse_iterator(iterator_type x) : current(x) {}

    reverse_iterator(const Self& x) : current(x.current) {}
    template <class Iter>
    reverse_iterator(const reverse_iterator<Iter>& x)
        : current(x.current) {}

    iterator_type base() const
    {
        return current;
    }
    reference operator*() const
    {
        Iterator tmp = current;
        return *--tmp;
    }
    pointer operator->() const
    {
        return &(operator*());
    }

    Self& operator++()
    {
        --current;
        return *this;
    }
    Self operator++(int)
    {
        Self tmp = *this;
        --current;
        return tmp;
    }
    Self& operator--()
    {
        ++current;
        return *this;
    }
    Self operator--(int)
    {
        Self tmp = *this;
        ++current;
        return tmp;
    }

    Self operator+(difference_type n) const
    {
        return Self(current - n);
    }
    Self& operator+=(difference_type n)
    {
        current -= n;
        return *this;
    }
    Self operator-(difference_type n) const
    {
        return _Self(current + n);
    }
    Self& operator-=(difference_type n)
    {
        current += n;
        return *this;
    }
    reference operator[](difference_type n) const
    {
        return *(*this + n);
    }
};

template <typename Iterator>
inline bool operator==(const reverse_iterator<Iterator>& x,
                       const reverse_iterator<Iterator>& y)
{
    return x.base() == y.base();
}

template <typename Iterator>
inline bool operator<(const reverse_iterator<Iterator>& x,
                      const reverse_iterator<Iterator>& y)
{
    return y.base() < x.base();
}

template <typename Iterator>
inline bool operator!=(const reverse_iterator<Iterator>& x,
                       const reverse_iterator<Iterator>& y)
{
    return !(x == y);
}

template <typename Iterator>
inline bool operator>(const reverse_iterator<Iterator>& x,
                      const reverse_iterator<Iterator>& y)
{
    return y < x;
}

template <typename Iterator>
inline bool operator<=(const reverse_iterator<Iterator>& x,
                       const reverse_iterator<Iterator>& y)
{
    return !(y < x);
}

template <typename Iterator>
inline bool operator>=(const reverse_iterator<Iterator>& x,
                       const reverse_iterator<Iterator>& y)
{
    return !(x < y);
}

template <typename Iterator>
inline typename reverse_iterator<Iterator>::difference_type
operator-(const reverse_iterator<Iterator>& x,
          const reverse_iterator<Iterator>& y)
{
    return y.base() - x.base();
}

template <typename Iterator>
inline reverse_iterator<Iterator>
operator+(typename reverse_iterator<Iterator>::difference_type n,
          const reverse_iterator<Iterator>& x)
{
    return x.operator+(n);
}

输入输出迭代器

输入迭代器有两个,分别为istream_iterator和istreambuf_iterator;输出迭代器有两个,分别为ostream_iterator和ostreambuf_iterator。
输入迭代器将自加操作转换为输入操作,输出迭代器将赋值转换为输出。
实现也不难,直接看源码吧。

template <class _Tp,
         class _CharT = char, class _Traits = char_traits<_CharT>,
         class _Dist = ptrdiff_t>
class istream_iterator
{
public:
    typedef _CharT                         char_type;
    typedef _Traits                        traits_type;
    typedef basic_istream<_CharT, _Traits> istream_type;

    typedef input_iterator_tag             iterator_category;
    typedef _Tp                            value_type;
    typedef _Dist                          difference_type;
    typedef const _Tp*                     pointer;
    typedef const _Tp&                     reference;

    istream_iterator() : _M_stream(0), _M_ok(false) {}
    istream_iterator(istream_type& s) : _M_stream(&s)
    {
        _M_read();
    }

    reference operator*() const
    {
        return _M_value;
    }
    pointer operator->() const
    {
        return &(operator*());
    }

    istream_iterator& operator++()
    {
        _M_read();
        return *this;
    }
    istream_iterator operator++(int)
    {
        istream_iterator tmp = *this;
        _M_read();
        return tmp;
    }

    bool _M_equal(const istream_iterator& x) const
    {
        return (_M_ok == x._M_ok) && (!_M_ok || _M_stream == x._M_stream);
    }

private:
    istream_type* _M_stream;
    _Tp _M_value;
    bool _M_ok;

    void _M_read()
    {
        _M_ok = (_M_stream && *_M_stream) ? true : false;
        if (_M_ok)
        {
            *_M_stream >> _M_value;
            _M_ok = *_M_stream ? true : false;
        }
    }
};

template <class _Tp, class _CharT, class _Traits, class _Dist>
inline bool
operator==(const istream_iterator<_Tp, _CharT, _Traits, _Dist>& x,
           const istream_iterator<_Tp, _CharT, _Traits, _Dist>& y)
{
    return x._M_equal(y);
}

template <class _Tp, class _CharT, class _Traits, class _Dist>
inline bool
operator!=(const istream_iterator<_Tp, _CharT, _Traits, _Dist>& x,
           const istream_iterator<_Tp, _CharT, _Traits, _Dist>& y)
{
    return !x._M_equal(y);
}


template <class _Tp, class _CharT = char, class _Traits = char_traits<_CharT> >
class ostream_iterator
{
public:
    typedef _CharT                         char_type;
    typedef _Traits                        traits_type;
    typedef basic_ostream<_CharT, _Traits> ostream_type;

    typedef output_iterator_tag            iterator_category;
    typedef void                           value_type;
    typedef void                           difference_type;
    typedef void                           pointer;
    typedef void                           reference;

    ostream_iterator(ostream_type& s) : _M_stream(&s), _M_string(0) {}
    ostream_iterator(ostream_type& s, const _CharT* c)
        : _M_stream(&s), _M_string(c)  {}
    ostream_iterator<_Tp>& operator=(const _Tp& value)
    {
        *_M_stream << value;
        if (_M_string) *_M_stream << _M_string;
        return *this;
    }
    ostream_iterator<_Tp>& operator*()
    {
        return *this;
    }
    ostream_iterator<_Tp>& operator++()
    {
        return *this;
    }
    ostream_iterator<_Tp>& operator++(int)
    {
        return *this;
    }
private:
    ostream_type* _M_stream;
    const _CharT* _M_string;
};

ostreambuf_iterator和istreambuf_iterator的源码在sbuf_iter.h文件中,我也没有细看,直接贴上来了。

template<typename _CharT, typename _Traits>
class ostreambuf_iterator
    : public iterator<output_iterator_tag, void, void, void, void>
{
public:
    typedef _CharT                           char_type;
    typedef _Traits                          traits_type;
    typedef basic_streambuf<_CharT, _Traits> streambuf_type;
    typedef basic_ostream<_CharT, _Traits>   ostream_type;

private:
    streambuf_type*     _M_sbuf;
    bool        _M_failed;

public:
    inline ostreambuf_iterator(ostream_type& __s) throw ()
        : _M_sbuf(__s.rdbuf()), _M_failed(!_M_sbuf) { }

    ostreambuf_iterator(streambuf_type* __s) throw ()
        : _M_sbuf(__s), _M_failed(!_M_sbuf) { }

    ostreambuf_iterator&
    operator=(_CharT __c);

    ostreambuf_iterator&
    operator*() throw()
    {
        return *this;
    }

    ostreambuf_iterator&
    operator++(int) throw()
    {
        return *this;
    }

    ostreambuf_iterator&
    operator++() throw()
    {
        return *this;
    }

    bool
    failed() const throw()
    {
        return _M_failed;
    }
};

template<typename _CharT, typename _Traits>
inline ostreambuf_iterator<_CharT, _Traits>&
ostreambuf_iterator<_CharT, _Traits>::operator=(_CharT __c)
{
    if (!_M_failed &&
            _Traits::eq_int_type(_M_sbuf->sputc(__c),_Traits::eof()))
        _M_failed = true;
    return *this;
}


template<typename _CharT, typename _Traits>
class istreambuf_iterator
    : public iterator<input_iterator_tag, _CharT, typename _Traits::off_type,
      _CharT*, _CharT&>
{
public:
    typedef _CharT                              char_type;
    typedef _Traits                             traits_type;
    typedef typename _Traits::int_type          int_type;
    typedef basic_streambuf<_CharT, _Traits>        streambuf_type;
    typedef basic_istream<_CharT, _Traits>          istream_type;
    typedef istreambuf_iterator<_CharT, _Traits>    __istreambufiter_type;

private:
    // If the end of stream is reached (streambuf_type::sgetc()
    // returns traits_type::eof()), the iterator becomes equal to
    // the "end of stream" iterator value.
    // NB: This implementation assumes the "end of stream" value
    // is EOF, or -1.
    streambuf_type*         _M_sbuf;
    int_type            _M_c;

public:
    istreambuf_iterator() throw()
        : _M_sbuf(NULL), _M_c(-2) { }

    istreambuf_iterator(istream_type& __s) throw()
        : _M_sbuf(__s.rdbuf()), _M_c(-2) { }

    istreambuf_iterator(streambuf_type* __s) throw()
        : _M_sbuf(__s), _M_c(-2) { }

    // NB: This should really have an int_type return
    // value, so "end of stream" postion can be checked without
    // hacking.
    char_type
    operator*() const
    {
        // The result of operator*() on an end of stream is undefined.
        char_type __ret;
        if (_M_sbuf && _M_c != static_cast<int_type>(-2))
            __ret = _M_c;
        else if (_M_sbuf)
            __ret = traits_type::to_char_type(_M_sbuf->sgetc());
        else
            __ret = static_cast<char_type>(traits_type::eof());
        return __ret;
    }

    __istreambufiter_type&
    operator++()
    {
        if (_M_sbuf)
            _M_sbuf->sbumpc();
        _M_c = -2;
        return *this;
    }

    __istreambufiter_type
    operator++(int)
    {
        __istreambufiter_type __old = *this;
        if (_M_sbuf)
            __old._M_c = _M_sbuf->sbumpc();
        _M_c = -2;
        return __old;
    }

    bool
    equal(const __istreambufiter_type& __b)
    {
        int_type __eof = traits_type::eof();
        bool __thiseof = !_M_sbuf || _M_sbuf->sgetc() == __eof;
        bool __beof = !__b._M_sbuf
                      || __b._M_sbuf->sgetc() == __eof;
        return (__thiseof && __beof || (!__thiseof && !__beof));
    }
};

template<typename _CharT, typename _Traits>
inline bool
operator==(const istreambuf_iterator<_CharT, _Traits>& __a,
           const istreambuf_iterator<_CharT, _Traits>& __b)
{
    return __a.equal(__b);
}

template<typename _CharT, typename _Traits>
inline bool
operator!=(const istreambuf_iterator<_CharT, _Traits>& __a,
           const istreambuf_iterator<_CharT, _Traits>& __b)
{
    return !__a.equal(__b);
}
<think>我们被要求详细解释C++ STL迭代器的使用方法和原理。根据提供的引用,我们可以总结出以下关键点: 1. 迭代器的作用:提供一种统一的方法来访问容器中的元素,而不需要暴露容器的内部结构。这样,算法可以独立于容器类型工作。 2. 迭代器与指针的关系:迭代器是泛化的指针,但并非所有迭代器都是指针。迭代器抽象了指针的行为,使得它可以用于不同的数据结构(如链表、树等)。 3. 迭代器的实现:根据容器的底层数据结构,迭代器可能被实现为原生态指针(如vector)或封装指针的类(如list)。迭代器类需要重载一些操作符,如解引用(*)、箭头(->)、自增(++)、自减(--)以及相等性比较(==, !=)等。 4. 迭代器的种类:包括输入迭代器、输出迭代器、前向迭代器、双向迭代器和随机访问迭代器等,不同种类的迭代器支持的操作不同。 5. 迭代器的失效:当容器发生改变(如插入或删除元素)时,某些迭代器可能会失效,继续使用它们会导致未定义行为。 我们将从以下几个方面展开: 一、迭代器的基本概念 二、迭代器的种类及其支持的操作 三、迭代器的实现原理(以vector和list为例) 四、迭代器的使用方法和注意事项 五、迭代器失效问题 下面开始详细说明: 一、迭代器的基本概念 迭代器STL的核心概念之一,它提供了访问容器中元素的方法,同时隐藏了容器的内部实现细节。迭代器类似于指针,可以指向容器中的某个元素,并能够通过解引用来访问该元素。迭代器之间可以通过自增或自减操作移动到相邻元素。 二、迭代器的种类及其支持的操作 STL定义了五种迭代器类别,每种支持的操作不同: 1. 输入迭代器(Input Iterator):只读,支持++、==、!=、*(读取)和->操作。只能单向移动(向前)。 2. 输出迭代器(Output Iterator):只写,支持++、*(写入)。只能单向移动(向前)。 3. 前向迭代器(Forward Iterator):可读写,支持输入和输出迭代器的所有操作,并且可以多次遍历同一个序列。例如单向链表(forward_list)的迭代器。 4. 双向迭代器(Bidirectional Iterator):支持前向迭代器的所有操作,还支持--(向后移动)。例如list、set、map的迭代器。 5. 随机访问迭代器(Random Access Iterator):支持双向迭代器的所有操作,还支持迭代器的算术运算(如+、-、+=、-=)、比较运算符(<、>、<=、>=)和下标访问([])。例如vector、deque、array的迭代器。 三、迭代器的实现原理 1. vector的迭代器:通常实现为原生态指针(T*),因为vector的元素在连续内存中,指针本身就满足随机访问迭代器的要求。 2. list的迭代器:由于list是双向链表,其迭代器需要封装链表节点指针,并重载相应的操作符。例如: - operator*():返回节点数据的引用。 - operator->():返回节点数据的指针。 - operator++()和operator++(int):移动到下一个节点。 - operator--()和operator--(int):移动到上一个节点。 - operator==和operator!=:比较两个迭代器是否指向同一个节点。 四、迭代器的使用方法和注意事项 1. 获取迭代器:每个容器都提供了begin()和end()成员函数,分别返回指向第一个元素和尾后元素(最后一个元素的下一个位置)的迭代器。 2. 遍历容器:通常使用循环,从begin()开始,直到end()结束。 ```cpp for (auto it = container.begin(); it != container.end(); ++it) { // 使用*it访问元素 } ``` 或者使用范围for循环(C++11起): ```cpp for (auto& element : container) { // 直接使用element } ``` 3. 使用迭代器时要注意其有效性:当容器发生改变(如插入、删除元素)时,迭代器可能会失效。例如,在vector中插入元素可能导致所有迭代器失效(因为重新分配内存),而在list中插入元素不会使迭代器失效(除了被删除元素的迭代器)。 五、迭代器失效问题 引用[3]提到,向容器插入或删除元素可能会改变容器中迭代器的有效性。例如: - vector:插入元素可能导致重新分配内存,使得所有迭代器、指针和引用失效。如果没有重新分配(如空间足够),则插入点之后的迭代器会失效。 - list:插入和删除操作不会使迭代器失效(除了被删除元素的迭代器)。 因此,在修改容器时,需要特别注意迭代器的有效性,避免使用失效的迭代器。 总结:迭代器STL中连接容器和算法的纽带,它提供了统一的访问接口,使得算法可以独立于容器类型。理解迭代器的种类、实现原理以及失效规则对于正确使用STL至关重要。 §§相关问题§§ 1. 迭代器失效的常见场景有哪些? 2. 如何设计一个自定义容器的迭代器? 3. STL迭代器与泛型算法如何协作? 4. 迭代器与指针相比有哪些优缺点?</think>### C++ STL迭代器使用与原理详解 #### 一、迭代器的作用与意义 迭代器STL的核心组件,作为**容器与算法之间的桥梁**(如`std::sort`、`std::find`等),它提供统一的访问接口,使算法无需关心底层容器实现细节。虽然指针可完成类似功能,但迭代器具有以下独特价值: 1. **泛型编程支持**:通过抽象容器访问方式,实现“一次编写,适用于所有容器” 2. **安全性增强**:封装指针操作,避免越界等错误 3. **适配复杂结构**:对链表、树等非连续结构提供类指针接口[^2] #### 二、迭代器的实现原理 迭代器的实现方式取决于容器底层数据结构: 1. **连续内存容器(vector, array)** - 直接封装原生指针(`T*`) - 支持随机访问(`operator[]`, `+n`等) ```cpp // vector迭代器简化实现 template<class T> class vector_iterator { T* ptr; public: T& operator*() { return *ptr; } // 解引用 iterator& operator++() { ++ptr; return *this; } // 前向移动 }; ``` 2. **链表容器(list, forward_list)** - 封装链表节点指针 - 需重载双向移动操作(`operator--`) ```cpp // list迭代器简化实现 template<class T> class list_iterator { ListNode<T>* node; public: T& operator*() { return node->data; } iterator& operator++() { node = node->next; return *this; } iterator& operator--() { node = node->prev; return *this; } // 双向移动 }; ``` 3. **关联容器(map, set)** - 通常基于红黑树实现 - 迭代器按中序遍历顺序移动 #### 三、迭代器类型与操作 | 迭代器类型 | 支持操作 | 对应容器示例 | |--------------------|-----------------------------------|--------------------------| | 输入迭代器 | `++`, `*`, `->`, `==` | `istream_iterator` | | 输出迭代器 | `++`, `*` | `ostream_iterator` | | 前向迭代器 | 输入迭代器所有操作 | `forward_list` | | 双向迭代器 | 前向迭代器 + `--` | `list`, `map`, `set` | | 随机访问迭代器 | 双向迭代器 + `+n`, `[]`, `<` 等 | `vector`, `array`, `deque` | #### 四、关键使用技巧 1. **获取迭代器** ```cpp vector<int> vec = {1,2,3}; auto begin = vec.begin(); // 指向首元素 auto end = vec.end(); // 指向尾后位置(哨兵) ``` 2. **遍历容器** ```cpp // 传统方式 for(auto it = vec.begin(); it != vec.end(); ++it) { cout << *it << " "; } // C++11范围for循环(本质使用迭代器) for(int val : vec) { cout << val << " "; } ``` 3. **与算法结合** ```cpp #include <algorithm> // 在[begin, end)区间查找元素 auto pos = find(vec.begin(), vec.end(), 2); if(pos != vec.end()) { cout << "Found at position: " << distance(vec.begin(), pos); } ``` #### 五、迭代器失效问题 容器修改可能导致迭代器失效: 1. **vector/string** - 插入元素可能引起扩容,**所有迭代器失效** - 删除元素使**被删位置之后**的迭代器失效 ```cpp vector<int> v = {1,2,3}; auto it = v.begin() + 1; v.push_back(4); // 可能扩容,it失效! ``` 2. **list/map/set** - 插入不会使迭代器失效 - 删除仅使**被删元素的迭代器**失效 ```cpp list<int> lst = {1,2,3}; auto it = ++lst.begin(); lst.erase(it); // 仅it失效,其他迭代器安全 ``` > **重要原则**:修改容器后应重新获取迭代器[^3] #### 六、迭代器特征萃取(iterator_traits) STL通过`iterator_traits`提取迭代器属性: ```cpp template<typename I> void algorithm(I first, I last) { // 获取迭代器距离类型 typename iterator_traits<I>::difference_type n = distance(first, last); // 获取元素引用类型 typename iterator_traits<I>::reference ref = *first; } ``` 特征包含五种类型:`value_type`, `difference_type`, `pointer`, `reference`, `iterator_category`[^4]。 #### 七、迭代器适配器 1. **反向迭代器**:`rbegin()` → `rend()` 2. **插入迭代器**:`back_inserter(vec)` 用于`copy`等算法 3. **流迭代器**:`istream_iterator<int>(cin)` 从输入流读取 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值