雨落无声

C++ 迭代器 Iterator
简介迭代器(Iterator)本质上就是一个指针(Pointer)。STD里面的容器(Container)一般都有...
扫描右侧二维码阅读全文
19
2018/02

C++ 迭代器 Iterator

简介

迭代器(Iterator)本质上就是一个指针(Pointer)。STD里面的容器(Container)一般都有迭代器,比如数组字符串VectorList 等。接下来使用迭代器的时候,我们可以将它视为指针(Pointer)来看。

前提知识

先看一段代码,理解 ::  这个符号的意思:

class A{
public:
   typedef unsigned int ui;
};

int main()
{
   A::ui b;
   return 0;
}

这里的A::ui b;就表示使用class A里面的ui这个东西来定义一个b变量。由此看来,:: 的作用就是用于直接使用某个 class 里面的公共成员的意思。

两种迭代器

Vector迭代器

我们先从简单的 Vector 开始:

#include <iostream>
#include <vector>

int main()
{
   std::vector<int> v;
   v.push_back(10);
   v.push_back(5);
   v.push_back(3);
   v.push_back(9);
   v.push_back(2);
   v.push_back(8);
   v.push_back(4);

   std::sort(v.begin(), v.end());

   for (unsigned int i =0;i<v.size();i++) {
      std::cout << v[i] << std::endl;
   }
   return 0;
}

这是一段最简单的排序Vector的程序,我们换成迭代器(Iterator)来写一份:

#include <iostream>
#include <vector>
    
int main()
{
    std::vector<int> v;
    v.push_back(10);
    v.push_back(5);
    v.push_back(3);
    v.push_back(9);
    v.push_back(2);
    v.push_back(8);
    v.push_back(4);
    
    //创建一个名为 start 的迭代器,让它指向 v 的第一个元素
    std::vector<int>::iterator start = v.begin(); 
    
    //创建一个名为 stop 的迭代器,让它指向 v 的末尾
    std::vector<int>::iterator stop = v.end();
    
    std::sort(start, stop);
    
    for (std::vector<int>::iterator i = v.begin(); i!=v.end() ; i++) {
        std::cout << *i << std::endl;
    }
    return 0;
}

上面这个例子中,我们将迭代器理解成指针就可以了。循环部分我们让 i 指向v的第一个元素,每次循环往后移动一位,直到到达 v 的结尾位置。*i表示取内存中地址为i的空间的值,与指针的操作是一样的。迭代器在定义的时候需要用对应的class来定义,但是使用上和指针没有什么区别。上述代码中的begin()end()方法或返回一个迭代器,也可以说是返回一个指针地址。为了能理解更深刻一些,我列举一下非常规的用法,但是HW千万别这么用。

#include <iostream>
#include <vector>
    
int main()
{
    std::vector<int> v;
    v.push_back(10);
    v.push_back(5);
    v.push_back(3);
    v.push_back(9);
    v.push_back(2);
    v.push_back(8);
    v.push_back(4);
    
    // v的第一个元素修改成 1000
    *v.begin() = 1000;
    
    // v的最后一个元素修改成 666
    *(v.end() - 1) = 666;
    
    for (std::vector<int>::iterator i = v.begin(); i!=v.end() ; i++) {
        std::cout << *i << std::endl;
    }
    return 0;
}

由此可见,其实迭代器就是指针,只不过定义方式有些区别而已。

这段代码中为什么要用v.end() - 1呢?因为end()其实指向最后一个元素的下一位,是一个不存在的地址,所以我们要往前移动一位才可以表示最后一个元素。切记:end()指向一个不存在的位置。

数组迭代器

Vector的迭代器是使用std::vector<>::iterator这种奇怪的方式来定义的,很多人可能会难以理解迭代器的真实身份。其实,数组是一个比较正常的容器,他的迭代器就比较熟悉,我们都用过。

#include <iostream>

int main()
{
    int a[5] = {5,4,3,2,1};
    
    // 迭代器 start 指向数组a的第一个元素
    int * start = a;
    
    // 迭代器 stop 指向数组的结尾位置(最后一个元素的后一位,是个不存在的地址)
    int * stop = a+5;
    
    
    for (int * i = start; i!=stop ;i++) {
        std::cout << *i << std::endl;
    }
    
    return 0;
}

上面的start,stop,i都是数组的迭代器,其实说白了就是指针,只不过换个迭代器的说法而已。

const iterator

有些容器有两种iterator:

  • const_iterator:只可以用来读取值,无法用来修改值。

  • iterator:可以随意修改和读取值。

看代码区分一下:

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v;
    
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    v.push_back(5);
    
    // 定义一个普通迭代器
    std::vector<int>::iterator i;
    
    // 定义一个只读迭代器
    std::vector<int>::const_iterator j;
    
    //迭代器 i 和 j 都指向v的第一个元素。
    i = v.begin();
    j = v.begin();
    
    // 可以使用迭代器 i 来修改值。
    *i = 20;
    
    // 不可使用 j 修改它对应的值。运行这句代码会出错。
    *j = 10;
    
    // j 只能像这样用来读取里面的值。
    while (j != v.end()) 
    {
        std::cout << *j << std::endl;
        j++;
    }
    
    return 0;
}

注意点

  1. 容器的end()指向容器最后一个元素的下一位,是一个不存在的位置。

  2. 在比较迭代器的时候,我们一般使用iterator != end()来作为循环条件,尽量不要使用<>之类的。

  3. 迭代器定义的时候会比较麻烦,除非作业要求用迭代器,一般使用[ ]会多一点。

Last modification:April 19th, 2018 at 01:38 am
If you think my article is useful to you, please feel free to appreciate

One comment

  1. 欣欣

    好久没写C++啦

Leave a Comment