3.4 迭代器介绍
3.4 迭代器介绍
可以使用下标运算符访问string对象的字符或vector对象的元素,使用迭代器也可以实现同样的目的。
除了vector之外,标准库还定义了其他几种容器。所有标准库容器都可以使用迭代器,但是只有几种支持下标运算符。严格来说,string对象不属于容器类型,但是string支持很多与容器类型类似的操作。
类似于指针类型,迭代器也提供了对对象的间接访问。就迭代器而言,其对象是容器中的元素或者string对象中的字符。使用迭代器可以访问某个元素,迭代器也能从一个元素移动到另外一个元素。迭代器有有效和无效之分,这一点和指针差不多。有效的迭代器或者指向某个元素,或者指向容器中尾元素的下一位置;其他所有情况都属于无效。
3.4.1 使用迭代器
和指针不一样的是,获取迭代器不是使用取地址符,有迭代器的类型同时拥有返回迭代器的成员。比如,这些类型都拥有名为begin和end的成员,其中begin成员负责返回指向第一个元素的迭代器。end成员负责返回指向容器“尾元素的下一位置”的迭代器,也就是说,该迭代器指示的是容器的一个本不存在的“尾后”元素。如果容器为空,则begin和end返回的是同一个迭代器,都是尾后迭代器。
// 由编译器决定b和e的类型。b表示v的第一个元素,e表示v的尾元素的下一位置
auto b = v.begin(), e = v.end(); //b和e的类型相同
迭代器运算符
标准容器迭代器的运算符 | |
---|---|
*iter | 返回迭代器iter所指元素的引用 |
iter->mem | 解引用iter并获取该元素的名为mem的成员,等价于(*iter).mem |
++iter | 令iter指示容器中的下一个元素 |
--iter | 令iter指示容器中的上一个元素 |
iter1 == iter2 | 判断两个迭代器是否相等,如果两个迭代器指示的是同一个元素或者它们是同一个容器的尾后迭代器,则相等;反之则不相等 |
iter1 != iter2 |
使用迭代器把string对象的第一个字母改为大写形式:
string s("some string");
if(s.begin() != s.end())
{
auto it = s.begin();
*it = toupper(*it);
}
将迭代器从一个元素移动到另外一个元素
迭代器使用递增运算符从一个元素移动到下一个元素。因为end返回的迭代器并不实际指示某个元素,所以不能对其进行递增或解引用的操作。
使用迭代器把string对象中的第一个单词改为大写形式:
// 依次处理s的字符直至处理完全部字符或者遇到空白
for(auto it = s.begin(); it != s.end() && !isspace(*it); ++it)
*it = toupper(*it);
迭代器类型
一般来说我们不知道(无须知道)迭代器的精确类型。而实际上,那些拥有迭代器的标准库类型使用iterator和const_iterator来表示迭代器的类型:
vector<int>::iterator it; // it能读写vector<int>的元素
string::iterator it2; // it2等读写string对象中的元素
vector<int>::const_iterator it3; // it3只能读元素,不能写元素
string::const_iterator it4; // it4只能读元素,不能写元素
如果vector对象或string对象是一个常量,只能使用const_iterator;如果vector对象或string对象不是常量,既能使用iterator也能使用const_iterator。
begin和end运算符
begin和end返回的具体类型由对象是否是常量决定,如果对象是常量,begin和end返回const_iterator;如果对象不是常量,返回iterator: