C++初阶 —— 迭代器

目录

迭代器的基本操作

输入迭代器 (Input Iterator)

输出迭代器 (Output Iterator)

前向迭代器 (Forward Iterator)

双向迭代器 (Bidirectional Iterator)

随机访问迭代器 (Random Access Iterator)

简单迭代器设计


        迭代器是 C++ STL 中的重要概念,是指向如数组或容器中某个元素的任何对象,能够使用一组运算符(至少有增量(++)和解引用(*)运算符)迭代该范围内的元素;它提供了一种统一的方法来遍历容器中的元素,无论容器的内部结构如何;

        迭代器最明显的形式是指针:指针可指向数组中的元素,并可使用增量运算符(++)迭代它们;也有其他类型的迭代器,如每个容器类型(如list)都有一个特定的迭代器类型,用于迭代其元素;

        虽然指针是迭代器的一种形式,但并非所有迭代器都具有相同的指针功能;根据迭代器支持的属性,分为五个不同的类别:

  • 输入迭代器 (Input Iterator),如istream_iterator
  • 输出迭代器 (Output Iterator),如ostream_iterator
  • 前向迭代器 (Forward Iterator),如forward_list
  • 双向迭代器 (Bidirectional Iterator),如listsetmap
  • 随机访问迭代器 (Random Access Iterator),如arrayvectordeque, 原生指针;

类别属性有效表达式
所有迭代器可拷贝构造可复制赋值可析构X b(a);
b = a;
可自增++a
a++

Random

Access

BidirectionalForwardInput支持等于、不等于比较a == b
a != b
作为右值解引用*a
a->m
Output作为左值解引用*a = t
*a++ = t
可默认构造X a;
X()
可多次遍历,解引用或自增都不影响解引用能力{ b=a; *a++; *b; }
可自减--a
a--
*a--
支持算术运算符+和-a + n
n + a
a - n
a - b
支持迭代器之间的不等式比较(<,>,<=和>=)a < b
a > b
a <= b
a >= b
支持复合赋值操作+=和-=a += n
a -= n
支持偏移解引用运算符([])a[n]
注,X表示一迭代器类型,a/b表示该迭代器类型的对象;

迭代器的基本操作

  • 所有迭代器都支持:*it,++it,it++,it1=it2,it1!=it2;
  • 双向迭代器额外支持:--it,it--;
  • 随机访问迭代器额外支持:it[n],it+/-n,it +=/-=n,it1-it2,it1</<=it2,it1>/>=it2;
//所有迭代器都支持:
*it        // 解引用
++it       // 前置递增
it++       // 后置递增
it1 == it2 // 相等比较
it1 != it2 // 不等比较
//双向迭代器额外支持:
--it       // 前置递减
it--       // 后置递减
//随机访问迭代器额外支持:
it[n]      // 下标访问
it + n     // 向前n个位置
it - n     // 向后n个位置
it += n    // 复合赋值
it -= n
it1 - it2  // 计算距离
it1 < it2  // 关系比较
it1 > it2
it1 <= it2
it1 >= it2

输入迭代器 (Input Iterator)

        输入迭代器代表了数据流中的一个位置,只能从该位置读取,然后只能前向移动;只能只读单次遍历,如:std::istream_iterator,所有标准容器至少支持前向迭代器类型

  • 只读,只能用于读取当前指向的元素,不能修改(解引用返回的是一个右值);
  • 单次遍历,输入迭代器最显著的特征,不保证自增一个迭代器,之前迭代器仍然有效;一旦移动了迭代器,之前位置和值可能”消失“;
    • 如对象std::cin,数据被读取一次后,无法在回退去重新读取;
value = *iter;
*iter = value; // 错误!输入迭代器不允许写
int main() {
    std::istream& input = std::cin; //对象cin拷贝构造函数是删除的,不可不添加&

    // 创建一个从标准输入读取整数的 istream_iterator
    // 当没有数据可读或发生错误时,等于默认构造的 "end" 迭代器
    std::istream_iterator<int> input_begin(std::input);
    std::istream_iterator<int> input_end; // 默认构造的迭代器表示结束位置
    std::vector<int> vec;

    // 将数据从输入迭代器复制到 vector 中,典型的单遍算法
    while (input_begin != input_end) {
        vec.push_back(*input_begin); // 读取值
        ++input_begin;               // 移动到流中的下一个值
    }
    // 或者,更简洁地使用 std::copy
    // std::copy(input_begin, input_end, std::back_inserter(vec));

    for (int val : vec) { std::cout << val << " "; }
    std::cout << std::endl;
    return 0;
}

输出迭代器 (Output Iterator)

        输出迭代器代表了一个可以写入数据的位置,可向该位置赋值,然后向前移动;最重要的特点是只写单次遍历,如:std::ostream_iterator

  • 只写,只能用于向指向的位置写入元素,不能用于读取;
  • 单次遍历,与输入迭代器类似,输出迭代器通常也只能遍历一次;一旦向位置写入数据并移动到下一个位置,通常就不能再回到之前的位置重新写入;
    • 如对象std::cout
  • 写入顺序性,必须按照顺序逐个写入,无自增迭代器的情况下,不应该对同一个位置进行多次赋值;每个位置应该只被赋值一次;
*iter = value;
value = *iter; // 错误!输出迭代器不允许读
int main() {
    std::vector<int> vec = { 1, 2, 3, 4, 5 };

    // 创建一个向标准输出写入整数的 ostream_iterator
    // 第一个参数是输出流,第二个参数是分隔符(在每个元素后输出)
    std::ostream_iterator<int> output_iter(std::cout, " ");

    for (auto i : vec){ *output_iter = i; }

    // 使用 std::copy 算法将 vector 的内容"复制"到输出迭代器
    // 这实际上就是将每个元素写入到 std::cout
    //std::copy(vec.begin(), vec.end(), output_iter);
    std::cout << std::endl;
    return 0;
}

前向迭代器 (Forward Iterator)

        前向迭代器支持读写访问多遍遍历;它保持了序列中位置的稳定性,允许多次遍历同一个序列,且多个迭代器可以独立地在序列中移动,如:forward_list

  • 可读可写
  • 多遍遍历,可多次遍历同一个序列,迭代器位置是稳定的,移动一个迭代器不会影响其他迭代器;
  • 迭代器持久性,迭代器在移动后仍然保持有效(++i == ++j);
  • 支持保存和重用,可保存一个前向迭代器的位置,稍后回到这个位置继续操作;
value = *iter; //可读
*iter = value; //可写 
int main() {
    std::forward_list<int> flist = { 1, 2, 3, 4, 5 };

    auto it = flist.begin(); // 获取前向迭代器 
    std::cout << "第一个元素: " << *it << std::endl; // 可以读取  
    *it = 100; // 可以写入
    std::cout << "修改后: " << *it << std::endl;

    // 多遍遍历
    std::cout << "第一遍遍历: ";
    for (auto elem : flist) {
        std::cout << elem << " ";
    }
    std::cout << "第二遍遍历: ";
    for (auto elem : flist) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;
    return 0;
}

双向迭代器 (Bidirectional Iterator)

        双向迭代器扩展了前向迭代器的功能,并增加了递减操作,使得迭代器可在序列中向前和向后移动;它保持了前向迭代器的所有特性,并增加了向后移动的能力,如:listsetmap 等都提供双向迭代器;

  • 双向移动
  • 保持所有前向迭代器特性
  • 支持反向算法,可使用std::reverse_iterator从后向前遍历;
++iter
--iter
int main() {
    std::list<int> numbers = { 1, 2, 3, 4, 5 };

    // 向前遍历
    for (auto it = numbers.begin(); it != numbers.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
    // 向后遍历
    for (auto it = std::prev(numbers.end()); it != numbers.begin(); --it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
    // 反向遍历
    for (auto it = numbers.rbegin(); it != numbers.rend(); ++it) {
        std::cout << *it << " ";
    }
    return 0;
}

随机访问迭代器 (Random Access Iterator)

        随机访问迭代器在双向迭代器的基础上增加了常数时间的随机访问能力;它支持像指针一样的算术运算,可以直接跳转到序列中的任意位置,如:arrayvectordeque原生指针都提供随机访问迭代器;

  • 常数时间随机访问,可直接跳转到任意位置,时间复杂度 O(1),支持像数组一样的索引访问;
  • 保持所有低级迭代器特性,可读可写、多遍遍历、双向移动;
  • 迭代器算术,可进行整数加减运算,可计算两个迭代器之间的距离;
  • 完整的关系比较,可比较两个迭代器的相对位置;
//随机访问迭代器额外支持:
it[n]      // 下标访问
it + n     // 向前n个位置
it - n     // 向后n个位置
it += n    // 复合赋值
it -= n
it1 - it2  // 计算距离
it1 < it2  // 关系比较
it1 > it2
it1 <= it2
it1 >= it2
int main() {
    vector<int> vec = { 10, 20, 30, 40, 50 };
    array<int, 5> arr = { 1, 2, 3, 4, 5 };
    int c_array[] = { 100, 200, 300, 400, 500 };

    // 这些都是随机访问迭代器
    auto vec_it = vec.begin();
    auto arr_it = arr.begin();
    int* ptr = c_array;

    // 随机访问
    cout << vec[2] << endl;
    cout <<  *(vec_it + 3) << endl;
    cout <<  vec_it[1] << endl;

    // 迭代器算术
    cout << vec.end() - vec.begin() << endl;
    return 0;
}

简单迭代器设计

//迭代器类定义在容器内部
class Iterator
{
private:
    int* m_ptr;
public:
    explicit Iterator(int* ptr) : m_ptr(ptr) {}

    int& operator*(); //解引用
    int* operator->(); //箭头运算

    Iterator& operator++(); //前缀递增
    Iterator operator++(int); //后缀递增  
    Iterator& operator--(); //前缀递减
    Iterator operator--(int); //后缀递增减

    //算术运算
    Iterator operator+(int n) const;
    Iterator operator-(int n) const

    //比较运算符
    bool operator==(const Iterator& other) const;
    bool operator!=(const Iterator& other) const;
    bool operator<(const Iterator& other) const;
    bool operator>(const Iterator& other) const;
    bool operator<=(const Iterator& other) const;
    bool operator>=(const Iterator& other) const;

    //下标访问
    int& operator[](int index);
}

class ConstIterator
{
    private:
        const int* m_ptr;
        
    public:
        explicit ConstIterator(const int* ptr) : m_ptr(ptr) {}

    const int& operator*() const; //解引用
    const int* operator->() const; //箭头运算

    constIterator& operator++(); //前缀递增
    constIterator operator++(int); //后缀递增  
    constIterator& operator--(); //前缀递减
    constIterator operator--(int); //后缀递增减

    //算术运算
    constIterator operator+(int n) const;
    constIterator operator-(int n) const

    //比较运算符
    bool operator==(const constIterator& other) const;
    bool operator!=(const constIterator& other) const;
    bool operator<(const constIterator& other) const;
    bool operator>(const constIterator& other) const;
    bool operator<=(const constIterator& other) const;
    bool operator>=(const constIterator& other) const;

    //下标访问
    const int& operator[](int index) const;  
}

//具体实现案例
#include <iostream>
#include <stdexcept>

class IntArray {
private:
    int* m_data;
    size_t m_size;
    
public:
    // 构造函数
    IntArray(size_t size = 0) : m_size(size) {
        m_data = new int[m_size];
        for (size_t i = 0; i < m_size; ++i) {
            m_data[i] = 0;
        }
    }
    
    // 拷贝构造函数
    IntArray(const IntArray& other) : m_size(other.m_size) {
        m_data = new int[m_size];
        for (size_t i = 0; i < m_size; ++i) {
            m_data[i] = other.m_data[i];
        }
    }
    
    // 析构函数
    ~IntArray() {
        delete[] m_data;
    }
    
    // 赋值运算符
    IntArray& operator=(const IntArray& other) {
        if (this != &other) {
            delete[] m_data;
            m_size = other.m_size;
            m_data = new int[m_size];
            for (size_t i = 0; i < m_size; ++i) {
                m_data[i] = other.m_data[i];
            }
        }
        return *this;
    }
    
    // 访问元素
    int& operator[](size_t index) {
        if (index >= m_size) {
            throw std::out_of_range("Index out of range");
        }
        return m_data[index];
    }
    
    const int& operator[](size_t index) const {
        if (index >= m_size) {
            throw std::out_of_range("Index out of range");
        }
        return m_data[index];
    }
    
    size_t size() const { return m_size; }
    
    // 迭代器类定义在容器内部
    class Iterator {
    private:
        int* m_ptr;
        
    public:
        // 构造函数
        explicit Iterator(int* ptr) : m_ptr(ptr) {}
        
        // 解引用运算符
        int& operator*() {
            return *m_ptr;
        }
        
        // 箭头运算符
        int* operator->() {
            return m_ptr;
        }
        
        // 前缀递增
        Iterator& operator++() {
            ++m_ptr;
            return *this;
        }
        
        // 后缀递增
        Iterator operator++(int) {
            Iterator temp = *this;
            ++m_ptr;
            return temp;
        }
        
        // 前缀递减
        Iterator& operator--() {
            --m_ptr;
            return *this;
        }
        
        // 后缀递减
        Iterator operator--(int) {
            Iterator temp = *this;
            --m_ptr;
            return temp;
        }
        
        // 算术运算
        Iterator operator+(int n) const {
            return Iterator(m_ptr + n);
        }
        
        Iterator operator-(int n) const {
            return Iterator(m_ptr - n);
        }
        
        // 比较运算符
        bool operator==(const Iterator& other) const {
            return m_ptr == other.m_ptr;
        }
        
        bool operator!=(const Iterator& other) const {
            return m_ptr != other.m_ptr;
        }
        
        bool operator<(const Iterator& other) const {
            return m_ptr < other.m_ptr;
        }
        
        bool operator>(const Iterator& other) const {
            return m_ptr > other.m_ptr;
        }
        
        bool operator<=(const Iterator& other) const {
            return m_ptr <= other.m_ptr;
        }
        
        bool operator>=(const Iterator& other) const {
            return m_ptr >= other.m_ptr;
        }
        
        // 下标访问
        int& operator[](int index) {
            return *(m_ptr + index);
        }
    };
    
    // 常量迭代器
    class ConstIterator {
    private:
        const int* m_ptr;
        
    public:
        explicit ConstIterator(const int* ptr) : m_ptr(ptr) {}
        
        // 常量版本的解引用
        const int& operator*() const {
            return *m_ptr;
        }
        
        const int* operator->() const {
            return m_ptr;
        }
        
        // 递增递减
        ConstIterator& operator++() {
            ++m_ptr;
            return *this;
        }
        
        ConstIterator operator++(int) {
            ConstIterator temp = *this;
            ++m_ptr;
            return temp;
        }
        
        ConstIterator& operator--() {
            --m_ptr;
            return *this;
        }
        
        ConstIterator operator--(int) {
            ConstIterator temp = *this;
            --m_ptr;
            return temp;
        }
        
        // 算术运算
        ConstIterator operator+(int n) const {
            return ConstIterator(m_ptr + n);
        }
        
        ConstIterator operator-(int n) const {
            return ConstIterator(m_ptr - n);
        }
        
        // 比较运算符
        bool operator==(const ConstIterator& other) const {
            return m_ptr == other.m_ptr;
        }
        
        bool operator!=(const ConstIterator& other) const {
            return m_ptr != other.m_ptr;
        }
        
        // 常量版本的下标访问
        const int& operator[](int index) const {
            return *(m_ptr + index);
        }
    };
    
    // 获取迭代器的方法
    Iterator begin() {
        return Iterator(m_data);
    }
    
    Iterator end() {
        return Iterator(m_data + m_size);
    }
    
    ConstIterator begin() const {
        return ConstIterator(m_data);
    }
    
    ConstIterator end() const {
        return ConstIterator(m_data + m_size);
    }
    
    ConstIterator cbegin() const {
        return ConstIterator(m_data);
    }
    
    ConstIterator cend() const {
        return ConstIterator(m_data + m_size);
    }
};

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值