STL快速上手2-迭代器

迭代器主要介绍

STL 迭代器是 STL 集合类(如 vectors、lists 等)的一部分。它提供一种统一的方式来访问集合中的元素。

主要有以下几种 STL 迭代器:

  1. 输入迭代器(Input iterator):只支持读操作,不支持修改或写入。
  2. 输出迭代器(Output iterator):只支持写操作,不支持读取。
  3. 前向迭代器(Forward iterator):支持前向遍历,只能单向访问元素。
  4. 双向迭代器(Bidirectional iterator):支持前向和后向遍历。
  5. 随机访问迭代器(Random-access iterator):支持随机访问,可以像数组那样访问。
  6. 环状迭代器(Circular iterator):到结尾后返回开始位置。
  7. 多路径迭代器(Multipass iterator):可多次遍历集合。
  8. 值类型迭代器(Value iterator):返回 iterator 实际持有的值。
  9. 插入迭代器(Insert iterator):特别用于向集合插入元素。

STL 中的集合类提供了 3 种类型的迭代器:

  • begin():返回一个指向第一个元素的迭代器。

  • end(): 返回一个迭代器,指向集合最后一个元素的下一个位置。

  • rbegin(): 返回一个指向最后一个元素的逆向迭代器。

主要作用:

  1. 提供统一的方式来访问 STL 集合中的元素。
  2. 隐藏底层集合的实现细节。
  3. 使 STL 算法可以在不同集合上运行。

输入迭代器

输入迭代器(Input Iterator)是最基本类型的迭代器,只支持单向遍历,并且只支持读取操作,不支持修改。

主要特点:

  1. 只能单向前进,不支持退格操作。
  2. 只支持读取操作,不支持修改元素。
  3. 不支持二元操作,如 ++it,it1 = it2 等。
  4. 不保证可重复读,一个元素可以读取多次,但读取结果不一定相同。
  5. 输入迭代器必须定义++,*,->,==,!= 这些操作。

主要用途:

  1. 只读访问集合中的元素。
  2. 对集合进行过滤或统计。

STL 中使用输入迭代器的典型场景:

  1. find_if():查找第一个满足条件的元素。
  2. count():统计满足条件的元素个数。
  3. for_each():对每个元素执行特定函数。
  4. copy():将一个序列复制到另一个序列。

这些算法都只需要读访问集合元素,所以使用输入迭代器足够。

输入迭代器定义的相关操作有:

  1. *it:解引用,获取当前元素。
  2. it++:移动到下一个元素。
  3. it == it2:判断两个迭代器是否指向同一个元素。
  4. it != it2:判断两个迭代器是否不同。

输出迭代器

输出迭代器(Output Iterator)是最低级的迭代器,只支持写操作,不支持读取。主要特点:

  1. 只支持写操作,不支持读取操作。
  2. 不支持二元操作,如++it 等。
  3. 可以多次写入同一个元素。
  4. 输出迭代器必须定义++,* = 这些操作。

主要用途:

  1. 将元素写入某个目标。可以是文件、网络流等。
  2. 将元素插入集合。

常见的使用输出迭代器的算法:

  1. copy():复制元素到输出迭代器。
  2. generate():生成元素到输出迭代器。
  3. sort():将排序后的元素写入输出迭代器。

输出迭代器定义的操作:

  1. *it = x:为当前元素赋值。
  2. it++:移动到下一个位置。

使用时,需要事先构造输出迭代器,指向目标。例如:

  • 写入文件:
ofstream file("out.txt");
ostream_iterator<int> out_iter(file, " ");
  • 插入集合:
vector<int> vec;
back_insert_iterator<vector<int>> vec_iter(vec);

前向迭代器

前向迭代器(Forward Iterator)支持从一个元素前进到下一个元素。主要特点:

  1. 支持前向遍历,不支持后退。
  2. 支持读写操作。可以读取和修改元素。
  3. 支持++it、*it、-> 等操作。
  4. 支持比较操作 == !=。
  5. 不保证可重复读。
  6. 可以复制迭代器。

STL 算法中使用前向迭代器:

  • for_each():对每个元素执行操作
  • find()/find_if():查找元素
  • transform():变换每个元素
  • replace():替换元素
  • copy():拷贝元素

前向迭代器实现的操作符:

  • *it:解引用
  • it++:移动到下一个元素
  • it == it2:比较两个迭代器是否指向同一个元素
  • it != it2:判断两个迭代器是否不同
  • it = it2:迭代器赋值

与输入迭代器相比:

  • 输入迭代器只支持读操作,前向迭代器同时支持读写操作
  • 输入迭代器不支持复制,前向迭代器支持复制
  • 前向迭代器效率略低于输入迭代器

双向迭代器

双向迭代器(Bidirectional Iterator)支持双重方向遍历,即可以前进也可以后退。

主要特点:

  1. 支持前向和后向遍历。
  2. 支持++it、–it 操作。
  3. 支持== != 、*it 等操作。
  4. 不保证可重复读。

用于 STL 容器:

  • list
  • forward_list(C++11)
  • deque

支持的 STL 算法:

  • 常见的前向迭代器支持的算法。
  • reverse():反转序列。
  • unique():去除相邻重复元素。

实现的操作:

  • 前向迭代器所有的操作
  • –it:后退一个元素

特点总结

  • 不仅支持前向遍历,还支持后向遍历。
  • 相比前向迭代器,支持更多操作。
  • 效率略低于前向迭代器。

随机访问迭代器

支持以下特点:

  1. 支持+ - * 运算。可实现 it += n; it - 3;*(it + 2) 等操作。
  2. 支持[]运算符,可以用it[n]访问元素。
  3. 两个随机访问迭代器可以用 - 运算符计算间隔。
  4. 具备所有的双向迭代器的功能。

环状迭代器

环状迭代器(Circular Iterator)是指当迭代器到达序列的末尾时,会循环回到序列的开头。相当于一个环。

主要特点:

  1. 当迭代器到达末尾时,会循环回到开始位置。

  2. 除此以外,与 STL 标准迭代器大致相同。

  3. 多用于循环访问有限序列。

用途:

  1. 实现有限状态机。
  2. 循环播放音视频。
  3. 游戏中的循环动画。

实现方式:

  1. 自定义迭代器,实现环状效果。

  2. 使用标准迭代器和机制。

例如:

vector<int> v = {
    
    1, 2, 3};

// 自定义迭代器
class CirIterator {
    
    
    int cur;
public:
    // 实现必要接口
    int& operator*() {
    
     return v[cur]; }
    CirIterator& operator++() {
    
    
        cur++;
        if (cur >= v.size()) cur = 0;
        return *this;
    }
};

// 使用标准迭代器
for (auto it = v.begin(); it != v.end(); ++it) {
    
    
    cout << *it;
}
cout << *v.begin();  // 打印第一个元素

多路径迭代器

多路径迭代器(Multipass Iterator)是指能够多次遍历相同的序列。

主要特点:

  1. 每次迭代后,迭代器位置被重新设置。
  2. 迭代器保持内部状态,知道序列的开始与结束位置。
  3. 除此以外,与 STL 标准迭代器相同。

实现方式有两种:

  1. 重新绑定迭代器。
iter = cont.begin();   // 重新绑定到序列开始
  1. 重新设置迭代器位置。
iter.reset();  // 重新设置迭代器,指向序列开始

主要用于:

  1. 多次对序列应用相同的操作。
  2. 实现可回溯的算法。

举例:

while (true) {
    
    
    for (auto it = v.begin(); it != v.end(); ++it) {
    
    
        // 对每个元素执行操作
    }
}

值类型迭代器

值类型迭代器(Value Iterator)每次解引用返回值为元素本身,而非元素引用。

与标准迭代器的区别:

  • 标准迭代器:***(it) 返回元素的引用。
  • 值类型迭代器:*it 返回元素本身的拷贝。

主要特点:

  1. 当解引用时返回一个值,而非元素引用。
  2. 需要额外存储元素值。
  3. 可以像值一样访问和传递。
  4. 除此之外,其他与标准迭代器相似。

实现:

自定义迭代器类,实现必要接口。

例如:

class ValueIterator {
    
    
public:
    ValueIterator(vector<int>::iterator iter)
        : iterator(iter) {
    
    }

    int operator*() {
    
    
        return *iterator;
    }

    // 实现其他必要接口
private:
    vector<int>::iterator iterator;
};

插入迭代器

插入迭代器(Insert Iterator)主要用于向集合中插入元素。

主要特点:

  1. 仅支持写入操作,不支持读取操作。
  2. 写入一个元素后,迭代器移动到下一位置。
  3. 写入元素后,原迭代器位置保持不变。
  4. 必须实现++和* =运算。

使用方式:

  1. 创建插入迭代器,指向集合。
vector<int> vec;
insert_iterator<vector<int>> iter(vec, vec.begin());
  1. 使用插入迭代器向集合插入元素。
*iter = 10;   // 将10插入vec
++iter;
*iter = 20;   // 将20插入vec

STL 中使用插入迭代器的算法:

  • copy():复制元素到插入迭代器。
  • generate():向插入迭代器生成元素。
  • transform():转换每个元素后插入。

主要用于:

  • 向集合插入元素。
  • 拷贝其他集合中的元素。
  • 生成元素插入集合。

通过创建插入迭代器,然后使用*it = x; ++it;的方式向集合插入元素。
主要应用在需要插入大量元素时使用。


猜你喜欢

转载自blog.csdn.net/delete_you/article/details/130966686
今日推荐