迭代器循环与索引循环 [英] Iterator Loop vs index loop

查看:143
本文介绍了迭代器循环与索引循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


可能重复:

为什么使用迭代器而不是数组索引?





<我正在回顾我对C ++的了解,我偶然发现了迭代器。我想知道的一件事是什么让他们如此特别,我想知道为什么:

I'm reviewing my knowledge on C++ and I've stumbled upon iterators. One thing I want to know is what makes them so special and I want to know why this:

using namespace std;

vector<int> myIntVector;
vector<int>::iterator myIntVectorIterator;

// Add some elements to myIntVector
myIntVector.push_back(1);
myIntVector.push_back(4);
myIntVector.push_back(8);

for(myIntVectorIterator = myIntVector.begin(); 
        myIntVectorIterator != myIntVector.end();
        myIntVectorIterator++)
{
    cout<<*myIntVectorIterator<<" ";
    //Should output 1 4 8
}

优于此:

using namespace std;

vector<int> myIntVector;
// Add some elements to myIntVector
myIntVector.push_back(1);
myIntVector.push_back(4);
myIntVector.push_back(8);

for(int y=0; y<myIntVector.size(); y++)
{
    cout<<myIntVector[y]<<" ";
    //Should output 1 4 8
}

是的我知道我不应该使用std命名空间。我刚把这个例子从cprogramming网站上删除了。那么请你告诉我为什么后者更糟?有什么大的区别?

And yes I know that I shouldn't be using the std namespace. I just took this example off of the cprogramming website. So can you please tell me why the latter is worse? What's the big difference?

推荐答案

关于迭代器的特殊之处在于它们提供了算法和容器。对于通用代码,建议使用STL算法的组合(例如 find sort 删除复制)等,执行您对数据结构的计算( vector list map 等),并将该算法与迭代器一起提供你的容器。

The special thing about iterators is that they provide the glue between algorithms and containers. For generic code, the recommendation would be to use a combination of STL algorithms (e.g. find, sort, remove, copy) etc. that carries out the computation that you have in mind on your data structure (vector, list, map etc.), and to supply that algorithm with iterators into your container.

您的特定示例可以写成 for_each 算法和<$ c $的组合c> vector 容器(见下面的选项3),但它只是四种不同的方法来迭代std :: vector:

Your particular example could be written as a combination of the for_each algorithm and the vector container (see option 3) below), but it's only one out of four distinct ways to iterate over a std::vector:

1)基于索引的迭代

for (std::size_t i = 0; i != v.size(); ++i) {
    // access element as v[i]

    // any code including continue, break, return
}

优点:熟悉C风格代码的人都熟悉,可循环使用不同的圣乘坐(例如 i + = 2 )。

Advantages: familiar to anyone familiar with C-style code, can loop using different strides (e.g. i += 2).

缺点:仅适用于顺序随机访问容器( vector array deque ),不起作用对于列表 forward_list 或关联容器。循环控制也有点冗长(init,check,increment)。人们需要了解C ++中基于0的索引。

Disadvantages: only for sequential random access containers (vector, array, deque), doesn't work for list, forward_list or the associative containers. Also the loop control is a little verbose (init, check, increment). People need to be aware of the 0-based indexing in C++.

2)基于迭代器的迭代

for (auto it = v.begin(); it != v.end(); ++it) {
    // if the current index is needed:
    auto i = std::distance(v.begin(), it); 

    // access element as *it

    // any code including continue, break, return
}

优点:更通用,适用于所有容器(即使是新的无序关联容器,也可以使用不同的步幅(例如 std :: advance(it,2));

Advantages: more generic, works for all containers (even the new unordered associative containers, can also use different strides (e.g. std::advance(it, 2));

缺点:需要额外的工作获取当前元素的索引(对于list或forward_list可以是O(N))。再次,循环控件有点冗长(init,check,increment)。

Disadvantages: need extra work to get the index of the current element (could be O(N) for list or forward_list). Again, the loop control is a little verbose (init, check, increment).

3)STL for_each算法+ lambda

std::for_each(v.begin(), v.end(), [](T const& elem) {
     // if the current index is needed:
     auto i = &elem - &v[0];

     // cannot continue, break or return out of the loop
});

优点:与2相同)加上小幅减少循环控制(否)检查和增加),这可以大大降低你的错误率(错误的初始化,检查或增加,逐个错误)。

Advantages: same as 2) plus small reduction in loop control (no check and increment), this can greatly reduce your bug rate (wrong init, check or increment, off-by-one errors).

缺点:与显式迭代器循环相同,加上循环中流控制的限制可能性(不能使用continue,break或return),并且没有不同步幅的选项(除非你使用重载 c> operator ++的迭代器适配器)。

Disadvantages: same as explicit iterator-loop plus restricted possibilities for flow control in the loop (cannot use continue, break or return) and no option for different strides (unless you use an iterator adapter that overloads operator++).

4)range-for循环

for (auto& elem: v) {
     // if the current index is needed:
     auto i = &elem - &v[0];

    // any code including continue, break, return
}

优点:非常紧凑的循环控制,可直接访问当前元素。

Advantages: very compact loop control, direct access to the current element.

缺点:额外的声明得到索引。不能使用不同的步幅。

Disadvantages: extra statement to get the index. Cannot use different strides.

使用什么?

针对您的具体示例迭代 std :: vector :如果你真的需要索引(例如访问上一个或下一个元素,在循环内打印/记录索引等)或者你需要一个不同于1的步幅,那么我会选择明确的索引循环,否则我会选择range-for循环。

For your particular example of iterating over std::vector: if you really need the index (e.g. access the previous or next element, printing/logging the index inside the loop etc.) or you need a stride different than 1, then I would go for the explicitly indexed-loop, otherwise I'd go for the range-for loop.

对于通用容器的通用算法,我会选择显式迭代器循环,除非代码在循环内部没有流控制并且需要步幅1,在这种情况下我是' d去STL for_each +一个lambda。

For generic algorithms on generic containers I'd go for the explicit iterator loop unless the code contained no flow control inside the loop and needed stride 1, in which case I'd go for the STL for_each + a lambda.

这篇关于迭代器循环与索引循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆