C/C++迭代器使用具体解释

简介:

迭代器是一种检查容器内元素并遍历元素的数据类型。能够替代下标訪问vector对象的元素。

每种容器类型都定义了自己的迭代器类型,如 vector:

vector<int>::iterator iter;
这符语句定义了一个名为 iter 的变量。它的数据类型是 vector<int> 定义的 iterator 类型。每一个标准库容器类型都定义了一个名为 iterator 的成员,这里的 iterator 与迭代器实际类型的含义同样。

begin 和 end 操作

每种容器都定义了一对命名为 begin 和 end 的函数,用于返回迭代器。假设容器中有元素的话。由 begin 返回的迭代器指向第一个元素:
vector<int>::iterator iter = ivec.begin();
上述语句把 iter 初始化为由名为 vector 操作返回的值。如果 vector 不空,初始化后,iter 即指该元素为 ivec[0]。

由 end 操作返回的迭代器指向 vector 的“末端元素的下一个”。表明它指向了一个不存在的元素。如果 vector 为空。begin 返回的迭代器与 end 返回的迭代器同样。由 end 操作返回的迭代器并不指向 vector 中不论什么实际的元素,相反,它仅仅是起一个哨兵(sentinel)的作用。表示我们已处理完 vector 中全部元素。


【备注:不用操心begin和end在循环中的条件推断。大胆使用吧!

vector 迭代器的自增和解引用运算

迭代器类型可使用 解引用操作符(dereference operator)( *)来訪问迭代器所指向的元素:
*iter = 0;
解引用操作符返回迭代器当前所指向的元素。如果 iter 指向 vector 对象 ivec 的第一元素,那么 *iter 和 ivec[0] 就是指向同一个元素。上面这个语句的效果就是把这个元素的值赋为 0。
迭代器使用自增操作符向前移动迭代器指向容器中下一个元素。从逻辑上说。迭代器的自增操作和 int 型对象的自增操作类似。对 int 对象来说。操作结果就是把 int 型值“加 1”,而对迭代器对象则是把容器中的迭代器“向前移动一个位置”。因此,假设 iter 指向第一个元素,则 ++iter 指向第二个元素。
因为 end 操作返回的迭代器不指向不论什么元素。因此不能对它进行解引用或自增操作。

迭代器的其它操作

还有一对可运行于迭代器的操作就是比較:用 == 或 != 操作符来比較两个迭代器,假设两个迭代器对象指向同一个元素。则它们相等,否则就不相等。

迭代器应用的程序演示样例

1、使用迭代器和下标改变vector的内容

这个非常easy,请看代码。
#include <iostream>
#include <string>
#include <vector>

int print_int_vector(std::vector<int> ivec)
{
	for(std::vector<int>::size_type ix =0, j = 0; ix != ivec.size(); ++ix, ++j)
	{
		std::cout<<ivec[ix]<<" "; //加空格!
	}
	std::cout<<std::endl;
	return 0;
}

int main()
{
	std::vector<int> ivec(10, 68); // empty vector
	print_int_vector(ivec);
	// reset all the elements in ivec to 0
	/*
        // 使用下标
	for (std::vector<int>::size_type ix = 0; ix != ivec.size(); ++ix)
	{
	    ivec[ix] = 0;
	}
	*/
	// equivalent loop using iterators to reset all the elements in ivec to 0
	for (std::vector<int>::iterator iter = ivec.begin(); iter != ivec.end(); ++iter)
		*iter = 0; // set element to which iter refers to 0
	print_int_vector(ivec);
	return 0;
}

2、tuple功能的实现【不可变性】

const_iterator类型仅仅能用于读取容器内元素。但不能改变其值。
当我们对普通 iterator 类型解引用时,得到对某个元素的非 const。而假设我们对 const_iterator 类型解引用时。 则能够得到一个指向 const 对象的引用),如同不论什么常量一样,该 对象不能进行重写。
假设使用const_itreator进行重写, 编译时会报错!
使用 const_iterator 类型时,我们能够得到一个迭代器,它自身的值能够改变。但不能用来改变其所指向的元素的值。

能够对迭代器进行自增以及使用解引用操作符来读取值,但不能对该元素赋值。

【注意:不要把 const_iterator 对象与 const 的 iterator 对象混淆起来。声明一个 const 迭代器时,必须初始化迭代器。一旦被初始化后。就不能改变它的值。】
vector<int> nums(10); // nums is nonconst
const vector<int>::iterator cit = nums.begin();
*cit = 1; // ok: cit can change its underlying element
++cit; // error: can't change the value of cit
【注意: const_iterator 对象能够用于 const vector 或非 const vector,由于不能改写元素值。

const 迭代器这样的类型差点儿没什么用处:一旦它被初始化后,仅仅能用它来改写其指向的元素,但不能使它指向不论什么其它元素。

tuple不可变的实现须要使用const声明。const vector<int> nums(10, 9);

总结

1、const_iterator 须要注意:这个vector本身还是可变的,仅仅只是对const_iterator类型解引用的对象不可变。

2、const迭代器也就是仅仅能指向其所指向的元素。不能通过++等操作去指向其它元素。可是,所指向这个元素能够改变。

3、须要定义真正tuple,那就用 const vector<int> nums(10, 9);来定义!

此时。必须使用const_iterator 来获取每一个元素的值。

迭代器的算术操作

1、能够对迭代器对象加上或减去一个整形值。这样做将产生一个新的迭代器,其位置在 iter 所指元素之前(加)或之后(减) n 个元素的位置。

加或减之后的结果必须指向 iter 所指 vector 中的某个元素。或者是 vector 末端的后一个元素。加上或减去的值的类型应该是 vector 的 size_type 或 difference_type 类型,样例:

int main()
{
	std::vector<int> ivec(10, 68); 
	print_int_vector(ivec);
	int i = 0;
	for (std::vector<int>::iterator iter = ivec.begin(); iter != ivec.end(); ++iter, i++)
		*iter = i; // set element to which iter refers to i
	print_int_vector(ivec);
	std::vector<int>::iterator iter = ivec.begin();
    iter += 100;
    std::cout<<*iter;

	return 0;
}
本样例中ivec有10个元素,iter+=j。j在10以内都不会有错(0~9),大于等于10则会 出现溢出问题编译器。执行中间都不会报错。能够加当然能够减。

2、iter1 - iter2:
该表达式用来计算两个迭代器对象的距离,该距离是名为 difference_type 的 signed 类型 size_type 的值,这里的 difference_type 是 signed 类型,由于减法运算可能产生负数的结果。该类型能够保证足够大以存储不论什么两个迭代器对象间的距离。

iter1 与 iter2 两者必须都指向同一 vector 中的元素,或者指向 vector 末端之后的下一个元素。

3、能够用迭代器算术操作来移动迭代器直接指向某个元素,比如。以下语句直接定位于 vector 中间元素:
vector<int>::iterator mid = vi.begin() + vi.size() / 2;
上述代码用来初始化 mid 使其指向 vi 中最靠近正中间的元素。

这样的直接计算迭代器的方法,与用迭代器逐个元素自增操作到达中间元素的方法是等价的,但前者的效率要高得多。

4、不论什么改变 vector 长度的操作都会使已存在的迭代器失效。

比如。在调用 push_back 之后,就不能再信赖指向 vector 的迭代器的值了。

请看样例:
*iter = i; // set element to which iter refers to i
ivec.push_back(i*2);
加上这句代码没问题,正确执行,可是。我们试图在for循环里面执行,即:
{
    *iter = i; // set element to which iter refers to i
    ivec.push_back(i*2);
}
则会莫名其妙 退出

本文由@The_Third_Wave(Blog地址:http://blog.csdn.net/zhanh1218)原创。

因为还有部分内容没有接触,仅仅讲了大概没有原因,会不定期更新。有错误请指正。

假设你看到这篇博文时发现不完整,那是我为防止爬虫先公布一半的原因,请看原作者Blog。

假设这篇博文对您有帮助,为了好的网络环境,不建议转载,建议收藏!假设您一定要转载,请



带上后缀和本文地址

本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5161078.html,如需转载请自行联系原作者

相关文章
|
4月前
|
C++ 容器
【C/C++笔记】迭代器
【C/C++笔记】迭代器
27 1
|
4月前
|
存储 安全 程序员
【C/C++笔记】迭代器范围
【C/C++笔记】迭代器范围
68 0
|
6月前
|
算法 数据处理 C++
C++一分钟之-迭代器与算法
【6月更文挑战第21天】C++ STL的迭代器统一了容器元素访问,分为多种类型,如输入、输出、前向、双向和随机访问。迭代器使用时需留意失效和类型匹配。STL算法如查找、排序、复制要求特定类型的迭代器,注意容器兼容性和返回值处理。适配器和算法组合增强灵活性,但过度使用可能降低代码可读性。掌握迭代器和算法能提升编程效率和代码质量。
55 3
|
6月前
|
编译器 C语言 C++
C++ STL中list迭代器的实现
C++ STL中list迭代器的实现
C++ STL中list迭代器的实现
|
6月前
|
存储 编译器 Linux
C++初阶学习第十弹——探索STL奥秘(五)——深入讲解vector的迭代器失效问题
C++初阶学习第十弹——探索STL奥秘(五)——深入讲解vector的迭代器失效问题
54 7
|
5月前
|
C++ 容器
【C++】string类的使用①(迭代器接口begin,end,rbegin和rend)
迭代器接口是获取容器元素指针的成员函数。`begin()`返回首元素的正向迭代器,`end()`返回末元素之后的位置。`rbegin()`和`rend()`提供反向迭代器,分别指向尾元素和首元素之前。C++11增加了const版本以供只读访问。示例代码展示了如何使用这些迭代器遍历字符串。
|
7月前
|
C语言
从C语言到C++_29(红黑树封装set和map)红黑树迭代器的实现(下)
从C语言到C++_29(红黑树封装set和map)红黑树迭代器的实现
49 3
|
7月前
|
算法 C语言 C++
从C语言到C++_20(仿函数+优先级队列priority_queue的模拟实现+反向迭代器)(上)
从C语言到C++_20(仿函数+优先级队列priority_queue的模拟实现+反向迭代器)
52 1
|
7月前
|
C语言 容器
从C语言到C++_17(list的模拟实现)list不是原生指针的迭代器(下 )
从C语言到C++_17(list的模拟实现)list不是原生指针的迭代器
29 1
|
7月前
|
C语言 计算机视觉
从C语言到C++_17(list的模拟实现)list不是原生指针的迭代器(中)
从C语言到C++_17(list的模拟实现)list不是原生指针的迭代器
33 1