C++基础教程面向对象(学习笔记(92))

STL迭代器概述

一个迭代器是一个对象,可以遍历(迭代)的容器类,而无需知道该容器是如何实现的。对于许多类(特别是列表和关联类),迭代器是访问这些类的元素的主要方式。

迭代器最好可视化为指向容器中给定元素的指针,并带有一组重载运算符以提供一组明确定义的函数:

Operator* 取消引用迭代器并且返回迭代器当前指向的元素。
Operator ++将迭代器移动到容器中的下一个元素。大多数迭代器也提供Operator–移动到前一个元素。
Operator==和Operator!= 基本比较运算符,用于确定两个迭代器是否指向同一个元素。要比较两个迭代器指向的值,首先取消引用迭代器,然后使用比较运算符。
Operator = - 将迭代器分配给新位置(通常是容器元素的开头或结尾)。要指定迭代器指向的元素的值,首先取消引用迭代器,然后使用assign运算符。
每个容器包括四个用于Operator =的基本成员函数:

begin()返回一个迭代器,表示容器中元素的开头。
end()返回一个迭代器,表示刚好超出元素末尾的元素。
cbegin()返回一个const(只读)迭代器,表示容器中元素的开头。
cend()返回一个const(只读)迭代器,表示元素刚刚结束的元素。
end()并不指向列表中的最后一个元素似乎很奇怪,但这主要是为了使循环变得容易:迭代元素可以继续,直到迭代器到达end(),然后你知道你了需要重做。

最后,所有容器都提供(至少)两种类型的迭代器:

container :: iterator提供了一个读/写迭代器
container :: const_iterator提供了一个只读迭代器
让我们看一下使用迭代器的一些例子。

通过向量迭代

#include <iostream>
#include <vector>
int main()
{
    using namespace std;
 
    vector<int> vect;
    for (int nCount=0; nCount < 6; nCount++)
        vect.push_back(nCount);
 
    vector<int>::const_iterator it; // 声明一个只读迭代器
    it = vect.begin(); //将它分配给向量的开头
    while (it != vect.end()) //虽然还没有到达终点
        {
        cout << *it << " "; // 打印它指向的元素的值
        ++it; // 并迭代到下一个元素
        }
 
    cout << endl;
}

这将打印以下内容:

0 1 2 3 4 5

迭代list

现在让我们用列表做同样的事情:

#include <iostream>
#include <list>
int main()
{
    using namespace std;
 
    list<int> li;
    for (int nCount=0; nCount < 6; nCount++)
        li.push_back(nCount);
 
    list<int>::const_iterator it; //声明一个迭代器
    it = li.begin(); // 将其分配到列表的开头
    while (it != li.end()) //虽然还没有到达终点
    {
        cout << *it << " "; //打印它指向的元素的值
        ++it; // 并迭代到下一个元素
    }
 
    cout << endl;
}

这打印:

0 1 2 3 4 5

请注意,代码几乎与矢量大小写相同,即使矢量和列表具有几乎完全不同的内部实现!

迭代填充

在下面的示例中,我们将从6个数字创建一个集合,并使用迭代器来打印集合中的值:

#include <iostream>
#include <set>
int main()
{
    using namespace std;
 
    set<int> myset;
    myset.insert(7);
    myset.insert(2);
    myset.insert(-6);
    myset.insert(8);
    myset.insert(1);
    myset.insert(-4);
 
    set<int>::const_iterator it; //声明一个迭代器
    it = myset.begin(); // 将其分配给集合的开头
    while (it != myset.end()) //虽然还没有到达终点
    {
        cout << *it << " "; // 打印它指向的元素的值
        ++it; // 并迭代到下一个元素
    }
 
    cout << endl;
}

该程序产生以下结果:

-6 -4 1 2 7 8

请注意,虽然填充集合与填充矢量和列表的方式不同,但用于迭代集合元素的代码基本相同。

迭代Maps

这个有点棘手。Maps和multimaps采用成对元素(定义为std :: pair)。我们使用make_pair()辅助函数来轻松创建对。std :: pair允许通过第一个和第二个成员访问该对的元素。在我们的地图中,我们首先使用第一个键作为键,然后使用第二个作为键。

#include <iostream>
#include <map>
#include <string>
int main()
{
    using namespace std;
 
    map<int, string> mymap;
    mymap.insert(make_pair(4, "apple"));
    mymap.insert(make_pair(2, "orange"));
    mymap.insert(make_pair(1, "banana"));
    mymap.insert(make_pair(3, "grapes"));
    mymap.insert(make_pair(6, "mango"));
    mymap.insert(make_pair(5, "peach"));
 
    map<int, string>::const_iterator it; //声明一个迭代器
    it = mymap.begin(); //将它分配给向量的开头
    while (it != mymap.end()) //虽然还没有到达终点
    {
        cout << it->first << "=" << it->second << " "; // 打印它指向的元素的值
        ++it; // 并迭代到下一个元素
    }
 
    cout << endl;
}

该程序产生结果:

1 =香蕉2 =橙色3 =葡萄4 =苹果5 =桃子6 =芒果

请注意迭代器如何轻松地遍历容器的每个元素。您根本不必关心Maps如何存储其数据!

Conclusion

迭代器提供了一种简单的方法来逐步执行容器类的元素,而无需了解容器类的实现方式。当与STL的算法和容器类的成员函数结合使用时,迭代器变得更加强大。在下一课中,您将看到使用迭代器将元素插入到列表中的示例(它不提供重载的operator []来直接访问其元素)。

值得注意的一点是:迭代器必须基于每个类实现,因为迭代器确实需要知道如何实现类。因此迭代器总是绑定到特定的容器类。

猜你喜欢

转载自blog.csdn.net/qq_41879485/article/details/84842833
今日推荐