迭代器介绍
迭代器是一种更通用的访问内容的机制 ,能提供 对对旬的间接访问。
3.4.1 使用迭代器
- 有迭代器的类型同时拥有返回迭代器成员,所有迭代器类型都有名为begin和end的成员,顾名思义,begin指向第一个成员,end指向结束的成员;
- 注意end不是一个有效成员,仅仅是一个标记,通常又被称为尾后迭代器;
- 当迭代器为空时,begin和end返回同一个迭代器;
- 迭代器支持的一些运算:
项目 | Value |
---|---|
*iter | 解引用,返回iter所指元素的引用 |
iter->men | 解引用并获取该元素的名为mem的成员,等价于(*iter).mem |
++iter | 指向容器中的下一个元素 |
–iter | 指向窗口中的上一个元素 |
iter1==iter2 | 判断两个迭代器是否相等,如果两个指向的是同一个元素或是同一个容器的尾后迭代器同相等,反之相反 |
iter1!=iter2 | 与==相同 |
- 通常我们不需要精确知道迭代器的精确类型,实际上,拥有迭代器的标准库类型使用iterator和const_iterator来表示迭代器的类型:
vector<int>::iterator it;
string::iterator it2;
vector<int>::const_iterator it3;
string::const_iterator it4;
- 一点自己的小理解:
与C#类型,iterator其实跟C#的IEnumerator类似,都是一个用于访问数据的接口
- 注意:在不可控的情况下,不要在循环中对容器进行增删操作,不要在自身的循环中进行会造成容器自身容量变化的操作;
- 这里出现了一个```->``符号,这个符号在项目中使用非常多,这次终于找到它的名字了:箭头运算符(这名字真够直接的)
3.4.1 练习
练习3.21
请使用迭代器重做3.3.3节的第一个练习
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<int> v1; //0个元素
cout << "v1的容量:" << v1.size() << endl;
for(auto it = v1.begin();it!=v1.end();it++)
{
cout << "v1的数据:" << *it << endl;
}
vector<int> v2(10); //10个元素,全部为0
cout << "v2的容量:" << v2.size() << endl;
for(auto it = v2.begin();it!=v2.end();it++)
{
cout << "v2的数据:" << *it << endl;
}
vector<int> v3(10, 42); //10个元素,全部为42
cout << "v3的容量:" << v3.size() << endl;
for(auto it = v3.begin();it!=v3.end();it++)
{
cout << "v3的数据:" << *it << endl;
}
vector<int> v4 {10} ; // 1个元素,值为10
cout << "v4的容量:" << v4.size() << endl;
for(auto it = v4.begin();it!=v4.end();it++)
{
cout << "v4的数据:" << *it << endl;
}
vector<int> v5 {10, 42}; //2个元素,分别为10和42
cout << "v5的容量:" << v5.size() << endl;
for(auto it = v5.begin();it!=v5.end();it++)
{
cout << "v5的数据:" << *it << endl;
}
vector<string> v6 {10}; //无法通过编译
cout << "v6的容量:" << v6.size() << endl;
for(auto it = v6.begin();it!=v6.end();it++)
{
cout << "v6的数据:" << *it << endl;
}
vector<string> v7 {10, "hi"}; //10个元素,全部是"hi"
cout << "v7的容量:" << v7.size() << endl;
for(auto it = v7.begin();it!=v7.end();it++)
{
cout << "v7的数据:" << *it << endl;
}
return 0;
}
答案与原来一样,不重放了。
练习 3.22
修改之前那个输出text第一段的程序 ,首先把text的第一段全都改成大写形式,然后再输出它
吐槽一波:谁TM知道你这说的是哪个程序啊- -找了半天都找不到,直接定义一个字符器修改了。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "hello world";
for (auto it = s.begin() ; it != s.end() ; ++it )
{
*it = toupper(*it);
}
cout << s << endl;
return 0;
}
输出结果:
HELLO WORLD.
练习3.23
编写一段程序 ,创建 一个含有 10个整数的vector对象,然后使用迭代器将所有元素的值 都变成原来的两部。输出 vector对象的内容 ,检验程序是否正确 。
#include <iostream>
using namespace std;
int main()
{
vector<int > v{1,2,3,4,5,6,7,8,9,10};
cout << "计算前的vector" << endl;
for(auto it = v.begin();it != v.end();it++)
{
cout << *it << "\t";
(*it) *= 2;
}
cout << endl;
cout << "计算后的vector" << endl;
for(auto it = v.begin();it != v.end();it++)
{
cout << *it << "\t";
}
cout << endl;
return 0;
}
输出结果:
计算前的vector
1 2 3 4 5 6 7 8 9 10
计算后的vector
2 4 6 8 10 12 14 16 18 20
3.4.2 迭代器运算
- vector和string中支持的运算
运算 | 作用 |
---|---|
iter + n | iter向后移动n个位置的元素,如果超出了末尾,会返回尾后迭代器 |
iter - n | iter向前移动n个位置的元素,如果超出了末尾,会返回尾后迭代器 |
iter += n | 加法复合语句,移动位置后将结果赋给iter |
iter -=n | 减法复合语句,移动位置后将结果赋给iter |
iter1 - iter2 | 返回两个迭代器之间的距离,参与运算的两个迭代器必须指向同一个容器中的元素或是尾后迭代器 |
>、<、>=、<= | 返回两个迭代器之间的位置关系 |
- Primer上给的一个经典二分查找实现,我这里将text的类型设为了int
vector<int> text{};
auto target = 10;
auto beg = text.begin(),end = text.end();
auto mid = text.begin() + (tend - beg)/2;
while (mid != end&& *mid != target)
{
if(target < mid)
{
end = mid;
}
else
{
begin = mid + 1;
}
mid = text.begin() + (tend - beg)/2;
}
3.4.2 练习
练习3.24
使用迭代器重做3.3.3节最后一个练习
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> input;
int tempInput;
while(cin){
cin >> tempInput;
input.push_back(tempInput);
}
cout << "输入总数:" << input.size() - 1<< endl;
for(auto i = input.begin(); i < input.end()-2 ; i++) //注意上面会多存一份
{
cout << "值:" << *i + *(i+1) << endl;
}
return 0;
}
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> input;
int tempInput;
while(cin){
cin >> tempInput;
input.push_back(tempInput);
}
cout << "输入总数:" << input.size() - 1 << endl;
input.erase(input.end()-1);
for (auto beg = input.begin(),end = input.end()-1; beg<=end;beg++,end-- )
{
if(beg!=end)
{
cout << "输出左边值:\t" << *(beg) << endl;
cout << "输出右边值:\t" << *(end) << endl;
}
else
{
cout << "输出中间值:\t" << *(end) << endl;
}
}
return 0;
}
练习3.26
在上面的二分搜索程序中,为什么用的是mid = beg+(end - beg)/2,而非mid = beg+(end + beg)/2?
一方面是没有定义vector的+运算,直接使用会导致语法错误;另一方面是两个迭代器相减返回的值是两个迭代器在容器之间的距离,是正确的写法。