在c++中迭代一个向量的正确方法是什么?

考虑这两个代码片段,这一个工作得很好:

for (unsigned i=0; i < polygon.size(); i++) {
    sum += polygon[i];
}

还有这个:

for (int i=0; i < polygon.size(); i++) {
    sum += polygon[i];
}

生成警告:有符号整数表达式和无符号整数表达式之间的比较。

对我来说,无符号变量看起来有点吓人,我知道无符号变量如果使用不当会很危险,所以-这是正确的吗?


当前回答

关于Johannes Schaub的回答:

for(std::vector<T*>::iterator it = v.begin(); it != v.end(); ++it) { 
...
}

这可能适用于某些编译器,但不适用于gcc。这里的问题是std::vector::iterator是类型、变量(成员)还是函数(方法)。使用gcc会得到以下错误:

In member function ‘void MyClass<T>::myMethod()’:
error: expected `;' before ‘it’
error: ‘it’ was not declared in this scope
In member function ‘void MyClass<T>::sort() [with T = MyClass]’:
instantiated from ‘void MyClass<T>::run() [with T = MyClass]’
instantiated from here
dependent-name ‘std::vector<T*,std::allocator<T*> >::iterator’ is parsed as a non-type, but instantiation yields a type
note: say ‘typename std::vector<T*,std::allocator<T*> >::iterator’ if a type is meant

解决方案是使用关键字'typename',如下所示:

typename std::vector<T*>::iterator it = v.begin();
for( ; it != v.end(); ++it) {
...

其他回答

为了完整,c++ 11语法只支持另一个版本的迭代器(ref):

for(auto it=std::begin(polygon); it!=std::end(polygon); ++it) {
  // do something with *it
}

哪一种也适合反向迭代

for(auto it=std::end(polygon)-1; it!=std::begin(polygon)-1; --it) {
  // do something with *it
}

模糊但重要的细节:如果你像下面这样说“for(auto it)”,你得到的是对象的副本,而不是实际的元素:

struct Xs{int i} x;
x.i = 0;
vector <Xs> v;
v.push_back(x);
for(auto it : v)
    it.i = 1;         // doesn't change the element v[0]

要修改vector的元素,需要将迭代器定义为引用:

for(auto &it : v)

关于Johannes Schaub的回答:

for(std::vector<T*>::iterator it = v.begin(); it != v.end(); ++it) { 
...
}

这可能适用于某些编译器,但不适用于gcc。这里的问题是std::vector::iterator是类型、变量(成员)还是函数(方法)。使用gcc会得到以下错误:

In member function ‘void MyClass<T>::myMethod()’:
error: expected `;' before ‘it’
error: ‘it’ was not declared in this scope
In member function ‘void MyClass<T>::sort() [with T = MyClass]’:
instantiated from ‘void MyClass<T>::run() [with T = MyClass]’
instantiated from here
dependent-name ‘std::vector<T*,std::allocator<T*> >::iterator’ is parsed as a non-type, but instantiation yields a type
note: say ‘typename std::vector<T*,std::allocator<T*> >::iterator’ if a type is meant

解决方案是使用关键字'typename',如下所示:

typename std::vector<T*>::iterator it = v.begin();
for( ; it != v.end(); ++it) {
...

我通常使用BOOST_FOREACH:

#include <boost/foreach.hpp>

BOOST_FOREACH( vector_type::value_type& value, v ) {
    // do something with 'value'
}

它适用于STL容器、数组、c风格字符串等。

for (vector<int>::iterator it = polygon.begin(); it != polygon.end(); it++)
    sum += *it;