c++的迭代器

C++ iterate over iterator

本文关键字:迭代器 c++      更新时间:2023-10-16

我目前正在"现代化"我的玩具编译器代码,以使用尽可能多的c++ 11特性来学习如何编写现代c++。在查看我的代码时,寻找要现代化的东西,我发现了这个结构:

for (size_t i = 0; i < _vector.size(); i++) {
   for (size_t j = 0; j < _vector[i].length(); j++) {

_vector是包含需要编译的文件源代码的std::vector<std::string>。向量中的每个std::string都是一行需要编译的代码。在编译之前,编译器检查要编译的代码是否有语法错误,检查的第一步是查找缺少的分号。我通过逐个查看每个字符并检查所述字符是否为分号来完成此操作。如果是,则通过构建一种小型语法树来检查分号是否需要,从而确定它是否必要。我目前使用_vector[i][j]访问每个字符,这让人想起ANSI-C(这就是您如何访问char*数组中的每个字符),我想用迭代器替换它。据我所知,迭代器是一种类似指针的结构,它指向容器/序列等中的元素。应用指针类比,我推断出std::vector<std::string>::iterator指向向量中的字符串,因此理论上的std::vector<std::string>::iterator::iterator将指向字符串对象中的单个字符。但是因为STL中没有这样的东西,所以指针类比在这里没有多大用处。所以我的问题是:我如何访问std::vector<std::string>::iterator中的每个字符?

如果您可以访问完整的c++ 11支持,为什么要为显式迭代器类型而烦恼呢?这就是auto的作用:

std::vector<std::string> sv;
//fill vector...
for(const auto& s : sv)
{
    for(const auto& c : s)
    {
        //'c' represents current character
    }
}

在这里使用range-base for循环。在第一个循环中,s是一个const引用(*)到vector中的当前字符串。由于std::string支持迭代语义,因此也可以使用for对其进行迭代。c是对字符串(s)中当前字符的const引用。

现场演示:点击


(*)因为你的循环似乎是只读的,所以应该使用const引用。如果您想执行任何修改,只需将此从const auto&更改为auto&

iterator的行为类似于指针。因此,在您的示例中,您可以解引用第一个迭代器以获得string,并使用std::string::iterator访问每个字符。

另一种方法是使用operator->()直接获取std::string::iterator,例如

for (std::vector<std::string>::iterator i = _vector.begin(); i != _vector.end(); ++i) {
    for (std::string::iterator j = i->begin(); j != i->end(); ++j) {
        /* ... */
    }
}

在c++ 11中,可以将其简化为

for (auto i = _vector.begin(); i != _vector.end(); ++i) {
    for (auto j = i->begin(); j != i->end(); ++j) {
        /* ... */
    }
}

正如@LightnessRacesinOrbit提到的和@MateuszGrzejek已经显示的那样,下一步将转向基于range的for循环。从第一个begin()元素到最后一个end()元素的循环

for (auto i = _vector.begin(); i != _vector.end(); ++i) {
    // Do something with string (*i)

可以写成

for (auto &s : _vector) {
    // Do something with string (s)

或者,如果您不修改string,则将其设置为const

for (const auto &s : _vector) {
    // Do something with string (s)