目录

  1. 迭代器的使用
  2. 迭代器的种类
  3. 迭代器的失效
  4. 迭代器的实现

1.迭代器的使用

为了提高C++编程的效率,STL中提供了许多容器,包括vector、list、map、set等。有些容器例如vector可以通过脚标索引的方式访问容器里面的数据,但是大部分的容器不能使用这种方式,例如list、map、set。STL中每种容器在实现的时候设计了一个内嵌的iterator类,不同的容器有自己专属的迭代器,使用迭代器来访问容器中的数据。除此之外,通过迭代器,可以将容器和通用算法结合在一起,只要给予算法不同的迭代器,就可以对不同容器执行相同的操作,例如find查找函数。迭代器对指针的一些基本操作如*、->、++、==、!=、=进行了重载,使其具有了遍历复杂数据结构的能力,其遍历机制取决于所遍历的数据结构,所有迭代的使用和指针的使用非常相似。通过begin,end函数获取容器的头部和尾部迭代器,end 迭代器不包含在容器之内,当begin和end返回的迭代器相同时表示容器为空。

template<typename InputIterator, typename T>
InputIterator find(InputIterator first, InputIterator last, const T &value)
{
while (first != last && *frist != value)
++first;
return first;
}
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
using namespace std; int main(int argc, const char *argv[])
{
int arr[] = { , , , , }; vector<int> iVec(arr, arr + );//定义容器vector
list<int> iList(arr, arr + );//定义容器list //在容器iVec的头部和尾部之间寻找整形数3
vector<int>::iterator iter1 = find(iVec.begin(), iVec.end(), );
if (iter1 == iVec.end())
cout<<"3 not found"<<endl;
else
cout<<"3 found"<<endl; //在容器iList的头部和尾部之间寻找整形数4
list<int>::iterator iter2 = find(iList.begin(), iList.end(), );
if (iter2 == iList.end())
cout<<"4 not found"<<endl;
else
cout<<"4 found"<<endl; return ;
}

2.迭代器的种类

根据迭代器所支持的操作,可以把迭代器分为5类。

1)   输入迭代器:是只读迭代器,在每个被遍历的位置上只能读取一次。例如上面find函数参数就是输入迭代器。

2)   输出迭代器:是只写迭代器,在每个被遍历的位置上只能被写一次。

3)   前向迭代器:兼具输入和输出迭代器的能力,但是它可以对同一个位置重复进行读和写。但它不支持operator--,所以只能向前移动。

4)   双向迭代器:很像前向迭代器,只是它向后移动和向前移动同样容易。

5)   随机访问迭代器:有双向迭代器的所有功能。而且,它还提供了“迭代器算术”,即在一步内可以向前或向后跳跃任意位置,  包含指针的所有操作,可进行随机访问,随意移动指定的步数。支持前面四种Iterator的所有操作,并另外支持it + n、it - n、it += n、 it -= n、it1 - it2和it[n]等操作。

STL每种容器类型都定义了 const_iterator,只能读取容器的值,不能修改所指向容器范围内元素的值。vector、string、Deque随机存取迭代器;List、Set、map、mutiset、multimap双向迭代器。

3.迭代器失效

容器的插入insert和erase操作可能导致迭代器失效,对于erase操作不要使用操作之前的迭代器,因为erase的那个迭代器一定失效了,正确的做法是返回删除操作时候的那个迭代器。

#include <vector>
using namespace std; int main(int argc, const char *argv[]) {
int arr[] = { , , , , }; vector<int> iVec(arr, arr + ); //定义容器vector
//迭代器失效
// for (vector<int>::iterator it = iVec.begin(); it != iVec.end();) {
// iVec.erase(it);
// }
//返回erase操作之后的迭代器
for (vector<int>::iterator it = iVec.begin();it != iVec.end();) {
it = iVec.erase(it);
}
return ;
}

4.迭代器的实现

STL中每个容器都有自己的迭代器,各种迭代器的接口相同,内部实现却不相同,这也直接体现了泛型编程的概念,下面在单链表类中内嵌入一个iterator的类来实现单链表的迭代

 #include <iostream>

 template<typename T>
struct ListNode {
T value;
ListNode* next;
ListNode() {
next = ;
}
ListNode(T val, ListNode *p = nullptr) :
value(val), next(p) {
}
}; template<typename T>
class List {
private:
ListNode<T> *m_pHead;
ListNode<T> *m_pTail;
int m_nSize;
public:
List() {
m_pHead = nullptr;
m_pTail = nullptr;
m_nSize = ;
}
//从链表尾部插入元素
void push_back(T value) {
if (m_pHead == nullptr) {
m_pHead = new ListNode<T>(value);
m_pTail = m_pHead;
} else {
m_pTail->next = new ListNode<T>(value);
m_pTail = m_pTail->next;
} } //打印链表元素
void print(std::ostream &os = std::cout) const {
for (ListNode<T> *ptr = m_pHead; ptr != m_pTail->next ; ptr = ptr->next)
std::cout << ptr->value << " ";
os << std::endl;
} //内置迭代器
class iterator {
private:
ListNode<T> *m_ptr;
public:
iterator(ListNode<T>* p = nullptr) :
m_ptr(p) {
} T operator*() const {
return m_ptr->value;
}
ListNode<T>* operator->() const {
return m_ptr;
}
iterator& operator++() {
m_ptr = m_ptr->next;
return *this;
}
iterator operator++(int) {
ListNode<T>* tmp = m_ptr;
m_ptr = m_ptr->next;
return iterator(tmp);
} bool operator==(const iterator &arg) const {
return arg.m_ptr == this->m_ptr;
} bool operator!=(const iterator &arg) const {
return arg.m_ptr != this->m_ptr;
} }; //返回链表头部指针
iterator begin() const {
return iterator(m_pHead);
} //返回链表尾部指针
iterator end() const {
return iterator(m_pTail->next);
} //其它成员函数 }; int main() {
List<int> l;
l.push_back();
l.push_back();
l.print();
for (List<int>::iterator it = l.begin(); it != l.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return ;
}

参考: http://blog.csdn.net/shudou/article/details/11099931

C++中迭代器原理、失效和简单实现的更多相关文章

  1. C++ STL迭代器原理和简单实现

    1. 迭代器简介 为了提高C++编程的效率,STL(Standard Template Library)中提供了许多容器,包括vector.list.map.set等.然而有些容器(vector)可以 ...

  2. C++ STL中迭代器失效的问题

    my_container.erase(iter); 其中my_container是STL的某种容器,iter是指向这个容器中某个元素的迭代器.如果不是在for,while循环中,这种方式删除元素没有问 ...

  3. 你的MySQL服务器开启SSL了吗?SSL在https和MySQL中的原理思考

    最近,准备升级一组MySQL到5.7版本,在安装完MySQL5.7后,在其data目录下发现多了很多.pem类型的文件,然后通过查阅相关资料,才知这些文件是MySQL5.7使用SSL加密连接的.本篇主 ...

  4. tomcat原理分析与简单实现

    tomcat原理分析与简单实现 https://blog.csdn.net/u014795347/article/details/52328221 2016年08月26日 14:48:18 卫卫羊习习 ...

  5. shiro中部分SpringCache失效问题

    原文:https://www.cnblogs.com/liruiloveparents/p/9392159.html shiro中部分SpringCache失效问题   1.问题抛出 今天在做Spri ...

  6. 有关ViewPager的使用及解决Android下ViewPager和PagerAdapter中调用notifyDataSetChanged失效的问题

    ViewPager是android-support-v4.jar包中的一个系统控件,继承自ViewGroup,专门用以实现左右滑动切换View的效果,使用时需要首先在Project->prope ...

  7. 在JavaScript中闭包的作用和简单的用法

    在JavaScript中闭包的作用和简单的用法 一.闭包的简介 作用域链:在js中只有函数有作用域的概念,由于函数内能访问函数外部的数据,而函数外部不能访问函数内部的数据,由上述形成一种作用域访问的链 ...

  8. Shiro框架 (原理分析与简单实现)

    Shiro框架(原理分析与简单实现) 有兴趣的同学也可以阅读我之前分享的:Java权限管理(授权与认证)CRM权限管理   (PS : 这篇博客里面的实现方式没有使用框架,完全是手写的授权与认证,可以 ...

  9. 分布式数据库中CAP原理(CAP+BASE)

    分布式数据库中CAP原理(CAP+BASE) 传统的ACID 1)原子性(Atomicity): 事务里的所有操作要么全部做完,要么都不做,事务成功的条件是事务里的所有操作都成功. 2)一致性(Con ...

随机推荐

  1. 老刘 Yii2 源码学习笔记之 Action 类

    Action 的概述 InlineAction 就是内联动作,所谓的内联动作就是放到controller 里面的 actionXXX 这种 Action.customAction 就是独立动作,就是直 ...

  2. CAS实战の简介

    一.SSO简介 单点登录的英文名称为Single Sign-On,简写为SSO,它是一个用户认证的过程,允许用户一次性进行认证之后,就访问系统中不同的应用:而不需要访问每个应用时,都重新输入密码.IB ...

  3. 用于sql代码实现用户的创建,以及不同用户之间登陆的切换

    --1.准备工作.创建两个登录名Create Login Login1 with Password='123456';Create Login Login2 with Password='123456 ...

  4. 使用Xcode 7 beta免费真机调试iOS应用程序

    使用Xcode 7 beta免费真机调试iOS应用程序 六月 9, 2015  |   K-Res 发布   今天凌晨的WWDC15虽然没有熬夜守候吧,但也还是早起第一时间翻看了twitter的相关标 ...

  5. Android SQLiteOpenHelper Sqlite数据库升级onUpgrade

    Android Sqlite数据库升级,在Android APP开发之中,非常常见: 在确定原来的数据库版本号之后,在原来数据库版本号+1,就会执行onUpgrade方法,进行数据库升级操作: 在on ...

  6. 如何充分利用 Windows Phone 高清屏幕

    Nokia 最近发布两款6寸大屏手机:Lumia 1520 和 Lumia 1320.为了支持这种设备 WP 升级了操作系统GDR3 支持了 1080P 的高清分辨率(1520),虽然GER3 是提供 ...

  7. CSS 温故而知新

    如何让文字垂直居中 需要设置div的height,line-height 为一样的值,如下所示: <div class="ui-bar ui-bar-e" style=&qu ...

  8. navicat远程连接oracle

    本机没有oracle,这个软件太大了. 想要远程连接oracle,本地不安装oracle的话是不行的,我们安装一个oracle instance client,然后配置navicat就ok了. 下载i ...

  9. 学习Spring Data JPA

    简介 Spring Data 是spring的一个子项目,在官网上是这样解释的: Spring Data 是为数据访问提供一种熟悉且一致的基于Spring的编程模型,同时仍然保留底层数据存储的特​​殊 ...

  10. wpf(使用定时器)使用定时器操作UI界面

    在项目实践中,我们 可能会遇到需要将一些控件上显示的内容只显示一段时间过后清空. 下面我们来实现这种操作: 首先需要注意的是:在wpf中涉及到界面操作的话,一定要使用定时器DispatcherTime ...