C++ STL Iterator 迭代器

26 篇文章 0 订阅
7 篇文章 0 订阅

Iterator 迭代器

Iterator(迭代器)模式又称 Cursor(游标)模式,用于提供一种方法顺序访问一个
聚合对象中各个元素, 而又不需暴露该对象的内部表示。

Iterator 模式是运用于聚合对象的一种模式,通过运用该模式,使得我们可以在不知道
对象内部表示的情况下,按照一定顺序(由 iterator 提供的方法)访问聚合对象中的各
个元素。

能够让迭代器与算法不干扰的相互发展,最后又能无间隙的粘合起来;

重载了 *,++,==,!=,= 运算符。用以操作复杂的数据结构

容器提供迭代器,算法使用迭代器;

STL 迭代器主要分为以下几类:

输入迭代器(Input Iterators):只能向前移动,每次只能读取一次元素。
            | 操作       | 说明                                         | 示例代码                                                     |
            |------------|----------------------------------------------|--------------------------------------------------------------|
            | `*it`      | 解引用迭代器,获取其指向的元素。             | `std::istream_iterator<int> input_iter(std::cin); int value = *input_iter;` |
            | `++it`     | 将迭代器向前移动一个位置。                   | `++input_iter;`                                              |
            |`it++`         | 将迭代器向前移动一个位置,并返回原位置。         | `input_iter++;`                                              |
            | `it1 == it2` | 比较两个输入迭代器是否相等。                 | `if (input_iter1 == input_iter2) { ... }`                    |
            | `it1 != it2` | 比较两个输入迭代器是否不相等。               | `if (input_iter1 != input_iter2) { ... }`                    |
            

输出迭代器(Output Iterators):只能向前移动,每次只能写入一次元素。
            
            | 操作       | 说明                                         | 示例代码                                                     |
            |------------|----------------------------------------------|--------------------------------------------------------------|
            | `*it = value` | 将值写入迭代器指向的位置。                | `std::ostream_iterator<int> output_iter(std::cout, " "); *output_iter = 42;` |
            | `++it`     | 将迭代器向前移动一个位置。传回新位置                 | `++output_iter;`                                             |
            |`it++`         | 将迭代器向前移动一个位置,并返回原位置。         | `output_iter++;`                                             |
            
前向迭代器(Forward Iterators):可以多次读写同一个元素,但只能向前移动。

            | 操作       | 说明                                         | 示例代码                                                     |
            |------------|----------------------------------------------|--------------------------------------------------------------|
            | `*it`      | 解引用迭代器,获取其指向的元素。             | `std::forward_list<int>::iterator it = flist.begin(); int value = *it;` |
            | `*it = value` | 将值写入迭代器指向的位置。                | `*it = 42;`                                                  |
            | `++it`     | 将迭代器向前移动一个位置。                   | `++it;`                                                      |
            |`it++`         | 将迭代器向前移动一个位置,并返回原位置。         | `it++;`                                                      |
            | `it1 == it2` | 比较两个前向迭代器是否相等。                 | `if (it1 == it2) { ... }`                                    |
            | `it1 != it2` | 比较两个前向迭代器是否不相等。               | `if (it1 != it2) { ... }`                                    |
          

双向迭代器(Bidirectional Iterators):在前向迭代器的基础上,增加了向后移动的能力。

            | 操作       | 说明                                         | 示例代码                                                     |
            |------------|----------------------------------------------|--------------------------------------------------------------|
            | `*it`      | 解引用迭代器,获取其指向的元素。             | `std::list<int>::iterator it = lst.begin(); int value = *it;` |
            | `*it = value` | 将值写入迭代器指向的位置。                | `*it = 42;`                                                  |
            | `++it`     | 将迭代器向前移动一个位置。                   | `++it;`                                                      |
            |`it++`         | 将迭代器向前移动一个位置,并返回原位置。         | `it++;`                                                      |
            | `--it`     | 将迭代器向后移动一个位置。                   | `--it;`                                                      |
            |`it--`         | 将迭代器向后移动一个位置,并返回原位置。         | `it--;`                                                      |
            | `it1 == it2` | 比较两个双向迭代器是否相等。                 | `if (it1 == it2) { ... }`                                    |
            | `it1 != it2` | 比较两个双向迭代器是否不相等。               | `if (it1 != it2) { ... }`                                    |

随机访问迭代器(Random Access Iterators):在双向迭代器的基础上,增加了随机访问的能力,可以进行指针算术运算。

            
            | 操作       | 说明                                         | 示例代码                                                     |
            |------------|----------------------------------------------|--------------------------------------------------------------|
            | `*it`      | 解引用迭代器,获取其指向的元素。             | `std::vector<int>::iterator it = vec.begin(); int value = *it;` |
            | `*it = value` | 将值写入迭代器指向的位置。                | `*it = 42;`                                                  |
            | `++it`     | 将迭代器向前移动一个位置。                   | `++it;`                                                      |
            |`it++`         | 将迭代器向前移动一个位置,并返回原位置。         | `it++;`                                                      |
            | `--it`     | 将迭代器向后移动一个位置。                   | `--it;`                                                      |
            |`it--`         | 将迭代器向后移动一个位置,并返回原位置。         | `it--;`                                                      |
            | `it += n`  | 将迭代器向前移动 n 个位置。                  | `it += 3;`                                                   |
            | `it -= n`  | 将迭代器向后移动 n 个位置。                  | `it -= 2;`                                                   |
            | `it + n`   | 返回指向 it 后面第 n 个位置的迭代器。        | `auto new_it = it + 5;`                                       |
            | `it - n`   | 返回指向 it 前面第 n 个位置的迭代器。        | `auto new_it = it - 3;`                                       |
            | `it1 - it2` | 返回两个迭代器之间的距离。                   | `auto distance = it1 - it2;`                                  |
            | `it1 < it2` | 比较两个迭代器,判断 it1 是否在 it2 之前。   | `if (it1 < it2) { ... }`                                      |
            | `it1 > it2` | 比较两个迭代器,判断 it1 是否在 it2 之后。   | `if (it1 > it2) { ... }`                                      |
            | `it1 <= it2` | 比较两个迭代器,判断 it1 是否在 it2 之前或相等。 | `if (it1 <= it2) { ... }`                                     |
            | `it1 >= it2` | 比较两个迭代器,判断 it1 是否在 it2 之后或相等。 | `if (it1 >= it2) { ... }`                                     |
            | `it1 == it2` | 比较两个随机访问迭代器是否相等。             | `if (it1 == it2) { ... }`                                    |
            | `it1 != it2` | 比较两个随机访问迭代器是否不相等。           | `if (it1 != it2) { ... }`                                    |

常见容器的迭代器

| 容器            | 支持的迭代器类别 |
|-----------------|------------------|
| `vector`        | 随机访问         |
| `deque`         | 随机访问         |
| `list`          | 双向             |
| `set`           | 双向             |
| `multiset`      | 双向             |
| `map`           | 双向             |
| `multimap`      | 双向             |
| `stack`         | 不支持           |
| `queue`         | 不支持           |
| `priority_queue`| 不支持           |

Auxiliary Iterator Functions 辅助迭代器函数

STL 提供了额外的 5 个函数,advance(),next(), prev(), distance(), iter_swap(),

前 4 个函数,是用于非 (随机存取迭代器) random-access Iterator,可以实现多步跨越。

最后一个函数用于交换两个 iterator。

| 函数原型                                                                 | 描述                                                                 |
|-------------------------------------------------------------------------|----------------------------------------------------------------------|
| `void advance (InputIterator& pos, Dist n)`                              | 将迭代器 `pos` 向前(或向后,如果 `n` 为负)移动 `n` 个位置。        |
| `ForwardIterator next (ForwardIterator pos)`                             | 返回一个指向 `pos` 后一个位置的迭代器。                              |
| `ForwardIterator next (ForwardIterator pos, Dist n)`                     | 返回一个指向 `pos` 后 `n` 个位置的迭代器。                           |
| `BidirectionalIterator prev (BidirectionalIterator pos)`                 | 返回一个指向 `pos` 前一个位置的迭代器。                              |
| `BidirectionalIterator prev (BidirectionalIterator pos, Dist n)`         | 返回一个指向 `pos` 前 `n` 个位置的迭代器。                           |
| `Dist distance (InputIterator pos1, InputIterator pos2)`                 | 计算从 `pos1` 到 `pos2` 的距离(元素个数)。                         |
| `void iter_swap (ForwardIterator1 pos1, ForwardIterator2 pos2)`          | 交换 `pos1` 和 `pos2` 指向的元素的值。                               |

#include <iostream>
#include <list>
#include <iterator>

int main() {
    // 创建一个包含整数的链表
    std::list<int> lst = {1, 2, 3, 4, 5};

    // 测试 advance 函数
    // advance 函数用于将迭代器向前或向后移动指定数量的位置
    std::list<int>::iterator it = lst.begin(); // 获取链表的起始迭代器
    std::advance(it, 2); // 将迭代器向前移动2个位置
    std::cout << "After advance(it, 2): " << *it << std::endl; // 输出 3

    // 测试 next 函数
    // next 函数返回一个指向当前迭代器之后第n个元素的迭代器
    std::list<int>::iterator nextIt = std::next(it); // 返回指向it之后第1个元素的迭代器
    std::cout << "After next(it): " << *nextIt << std::endl; // 输出 4

    nextIt = std::next(it, 2); // 返回指向it之后第2个元素的迭代器
    std::cout << "After next(it, 2): " << *nextIt << std::endl; // 输出 5

    // 测试 prev 函数
    // prev 函数返回一个指向当前迭代器之前第n个元素的迭代器
    std::list<int>::iterator prevIt = std::prev(it); // 返回指向it之前第1个元素的迭代器
    std::cout << "After prev(it): " << *prevIt << std::endl; // 输出 2

    prevIt = std::prev(it, 2); // 返回指向it之前第2个元素的迭代器
    std::cout << "After prev(it, 2): " << *prevIt << std::endl; // 输出 1

    // 测试 distance 函数
    // distance 函数计算两个迭代器之间的距离
    std::list<int>::iterator start = lst.begin(); // 获取链表的起始迭代器
    std::list<int>::iterator end = lst.end(); // 获取链表的结束迭代器
    std::cout << "Distance from start to end: " << std::distance(start, end) << std::endl; // 输出 5

    // 测试 iter_swap 函数
    // iter_swap 函数交换两个迭代器指向的元素
    std::list<int>::iterator it1 = lst.begin(); // 获取链表的起始迭代器
    std::list<int>::iterator it2 = std::next(lst.begin(), 2); // 获取链表的第3个元素的迭代器
    std::iter_swap(it1, it2); // 交换it1和it2指向的元素
    std::cout << "After iter_swap(it1, it2): ";
    for (int i : lst) {
        std::cout << i << " ";
    }
    std::cout << std::endl; // 输出 3 2 1 4 5

    return 0;
}

Reverse Iterators 反向迭代器

反向迭代器(Reverse Iterators)是一种特殊的迭代器,用于以相反的顺序遍历容器中的元素。
在C++标准库中,许多容器(如std::vector、std::list、std::deque等)都支持反向迭代器。

反向迭代器通常通过容器的rbegin()和rend()方法来获取。
rbegin()返回指向容器最后一个元素的反向迭代器,而rend()返回指向容器第一个元素之前的反向迭代器。

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 使用反向迭代器遍历vector
    for (auto rit = vec.rbegin(); rit != vec.rend(); ++rit) {
        std::cout << *rit << " ";
    }
    std::cout << std::endl;

    return 0;
}

Insert Iterators 插入迭代器

插入迭代器(Insert Iterators)是一种特殊的迭代器适配器,用于在容器的特定位置插入元素,而不是覆盖或替换现有元素。插入迭代器主要有三种类型:

back_insert_iterator:在容器的末尾插入元素。

front_insert_iterator:在容器的开头插入元素。

insert_iterator:在容器的指定位置插入元素。

这些插入迭代器通常与标准库的算法(如std::copy)一起使用,以便在复制元素时将它们插入到目标容器中。

示例

使用 back_insert_iterator

#include <iostream>
#include <vector>
#include <iterator>

int main() {
    std::vector<int> source = {1, 2, 3, 4, 5};
    std::vector<int> destination;

    // 使用 back_insert_iterator 将 source 的元素插入到 destination 的末尾
    std::copy(source.begin(), source.end(), std::back_inserter(destination));

    // 输出 destination 的内容
    for (int x : destination) {
        std::cout << x << " ";
    }
    std::cout << std::endl;

    return 0;
}

使用 front_insert_iterator

#include <iostream>
#include <deque>
#include <iterator>

int main() {
    std::deque<int> source = {1, 2, 3, 4, 5};
    std::deque<int> destination;

    // 使用 front_insert_iterator 将 source 的元素插入到 destination 的开头
    std::copy(source.begin(), source.end(), std::front_inserter(destination));

    // 输出 destination 的内容
    for (int x : destination) {
        std::cout << x << " ";
    }
    std::cout << std::endl;

    return 0;
}

使用 insert_iterator

#include <iostream>
#include <vector>
#include <iterator>

int main() {
    std::vector<int> source = {1, 2, 3, 4, 5};
    std::vector<int> destination = {10, 20, 30};

    // 使用 insert_iterator 将 source 的元素插入到 destination 的指定位置
    std::copy(source.begin(), source.end(), std::inserter(destination, destination.begin() + 1));

    // 输出 destination 的内容
    for (int x : destination) {
        std::cout << x << " ";
    }
    std::cout << std::endl;

    return 0;
}

流迭代器(Stream Iterators)

用于将输入输出流(如std::istream和std::ostream)与标准库算法和容器结合起来。流迭代器主要有两种类型:

istream_iterator:用于从输入流中读取数据。
ostream_iterator:用于向输出流中写入数据。

示例

使用 istream_iterator

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

int main() {
    // 从标准输入流中读取整数,并存储到 vector 中
    std::vector<int> vec((std::istream_iterator<int>(std::cin)), std::istream_iterator<int>());

    // 输出 vector 的内容
    std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>(std::cout, " "));
    std::cout << std::endl;

    return 0;
}

使用 ostream_iterator

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 将 vector 的内容输出到标准输出流
    std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>(std::cout, " "));
    std::cout << std::endl;

    return 0;
}

结合使用 istream_iterator 和 ostream_iterator

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

int main() {
    // 从标准输入流中读取整数,并存储到 vector 中
    std::vector<int> vec((std::istream_iterator<int>(std::cin)), std::istream_iterator<int>());

    // 将 vector 的内容输出到标准输出流
    std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>(std::cout, " "));
    std::cout << std::endl;

    return 0;
}

STL 内建仿函数

| 类别       | 仿函数名称       | 描述                                     |
|------------|------------------|------------------------------------------|
| 算术仿函数 | plus<T>          | 加法仿函数,用于两个元素相加             |
|            | minus<T>         | 减法仿函数,用于两个元素相减             |
|            | multiplies<T>    | 乘法仿函数,用于两个元素相乘             |
|            | divides<T>       | 除法仿函数,用于两个元素相除             |
|            | modulus<T>       | 取模仿函数,用于两个元素取模             |
|            | negate<T>        | 取反仿函数,用于元素取反                 |
| 比较仿函数 | equal_to<T>      | 等于仿函数,用于判断两个元素是否相等     |
|            | not_equal_to<T>  | 不等于仿函数,用于判断两个元素是否不相等 |
|            | greater<T>       | 大于仿函数,用于判断一个元素是否大于另一个元素 |
|            | less<T>          | 小于仿函数,用于判断一个元素是否小于另一个元素 |
|            | greater_equal<T> | 大于等于仿函数,用于判断一个元素是否大于或等于另一个元素 |
|            | less_equal<T>    | 小于等于仿函数,用于判断一个元素是否小于或等于另一个元素 |
| 逻辑仿函数 | logical_and<T>   | 逻辑与仿函数,用于两个元素的逻辑与操作   |
|            | logical_or<T>    | 逻辑或仿函数,用于两个元素的逻辑或操作   |
|            | logical_not<T>   | 逻辑非仿函数,用于元素的逻辑非操作       |

functor adapters binders

Binders(绑定器)

绑定器用于将函数的部分参数绑定到特定的值,从而生成一个新的函数对象。
C++标准库提供了std::bind和std::placeholders来实现这一功能。

#include <iostream>
#include <functional>
using namespace std;
using namespace std::placeholders; // 引入占位符命名空间
class A{
    public:
    void print(int x,int y){
        cout<<"x : "<<x<<endl;
        cout<<"y : "<<y<<endl;
    }
};

int main(){
    A a;

    auto f= bind(&A::print,a,1,2); //绑定对象a的print函数,并传入参数1和2
    f(); //调用绑定函数

    auto f1=bind(&A::print,_1,_2,_3);
    f1(a,1,2); //调用绑定函数,传入参数a,1,2

    auto f2=bind(&A::print,_1,100,200);
    f2(a);

    auto f3=bind(&A::print,a,_1,_2);
    f3(55,66);
    return 0;
}
#include <functional>
#include <algorithm>
#include <vector>
#include <iostream>
#include <string>
using namespace std;
using namespace std::placeholders;
class Person // 定义Person类
{
private:
    string name; // 私有成员变量,存储人的名字
public:
    Person (const string& n) : name(n) // 构造函数,初始化name成员变量
    {
    }
    void print () const // 成员函数,打印名字
    {
        cout << name << endl;
    }
    void print2 (const string& prefix) const // 成员函数,打印带前缀的名字
    {
        cout << prefix << name << endl;
    }
};

int main()
{
    Person p("abc"); // 创建一个Person对象,名字为"abc"
    auto mem = bind(&Person::print, p); // 使用bind绑定Person对象p的print成员函数
    mem(); // 调用绑定后的函数对象,打印"abc"

    vector<Person> vp = { // 创建一个Person对象的vector,包含三个Person对象
            Person("Tick"),
            Person("Trick"),
            Person("Track")
    };

    for_each (vp.begin(), vp.end(), // 使用for_each算法遍历vector中的每个Person对象
              bind(&Person::print, _1)); // 绑定每个Person对象的print成员函数,打印每个对象的名字
    cout << endl; // 打印换行

    for_each (vp.begin(), vp.end(), // 使用for_each算法遍历vector中的每个Person对象
              bind(&Person::print2, _1, "Person: ")); // 绑定每个Person对象的print2成员函数,并传入前缀"Person: ",打印带前缀的名字
    cout << endl; // 打印换行

    bind(&Person::print2, _1, "This is: ")(Person("nico")); // 直接使用bind绑定Person::print2成员函数,并传入前缀"This is: ",然后立即调用,打印"This is: nico"

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可能只会写BUG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值