使用'for'循环遍历C ++ Vector

我是C ++语言的新手。 我已经开始使用向量,并且已经注意到,在我看到的所有代码中,通过索引遍历一个向量, for循环的第一个参数总是基于向量。 在Java中,我可以用ArrayList做这样的事情:

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

有没有一个原因,我没有看到这在C + +? 这是不好的做法吗?

有什么理由我没有看到这在C + +? 这是不好的做法吗?

不,这不是一个坏习惯,但是它使你的代码具有一定的灵活性

通常,pre-C ++ 11迭代容器元素的代码使用迭代器,如下所示:

 std::vector<int>::iterator it = vector.begin(); 

这是因为它使代码更加灵活。

所有的标准库容器都支持和提供迭代器,并且假如在开发的后期你需要切换另一个容器,那么这个代码就不需要改变了。

注意:编写与每个可能的标准库容器一起工作的代码并不像看起来似的那样容易。

你没有看到这样的做法的原因是相当主观的,不能有一个确定的答案,因为我已经看到了许多使用你提到的方式,而不是iterator样式代码的代码。

以下可能是人们不考虑vector.size()循环方式的原因:

  1. 在循环条件下每次调用size()都是偏执的。 但是,这是一个没有问题的问题,或者可以被轻易修复
  2. 优先使用for循环本身的std::for_each()
  3. 之后将容器从std::vector更改为另一个(例如maplist )也会要求更改循环机制,因为不是每个容器都支持size()样式的循环

C ++ 11提供了一个很好的方法来移动容器。 这就是所谓的“基于循环的范围”(或Java中的“增强for循环”)。

用很less的代码,你可以遍历整个(强制!) std::vector

 vector<int> vi; ... for(int i : vi) cout << "i = " << i << endl; 

遍历一个向量的最简洁的方法是通过迭代器:

 for (auto it = begin (vector); it != end (vector); ++it) { it->doSomething (); } 

或(相当于上面的)

 for (auto & element : vector) { element.doSomething (); } 

在C ++ 0x之前,你必须用迭代器typesreplaceauto,并使用成员函数而不是全局函数开始和结束。

这可能是你所看到的。 与您提到的方法相比,优点是您不会严重依赖于vector的types。 如果将vector更改为不同的“集合类”类,则代码可能仍然有效。 但是,您也可以在Java中做类似的事情。 概念上没有太大差别; 然而,C ++使用模板来实现这一点(与Java中的generics相比)。 因此该方法适用于所有定义了beginend函数的types,即使对于非types的types(如静态数组)也是如此。 在这里看到: 如何基于范围为普通数组工作?

正确的做法是:

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

其中T是向量中类的types。 例如,如果该类是CActivity,只需要编写CActivity而不是T.

这种types的方法将在每个STL上工作(不仅仅是向量,这有点更好)。

如果你还想使用索引,方法是:

 for(std::vector<T>::size_type i = 0; i != v.size(); i++) { v[i].doSomething(); } 

使用迭代器有两个强有力的理由,其中一些在这里提到:

稍后切换容器不会使您的代码无效。

即如果你从一个std :: vector到一个std :: list或者std :: set,你不能使用数字索引来获得你所包含的值。 使用迭代器仍然有效。

运行时捕获无效的迭代

如果你在你的循环中修改你的容器,下一次你使用你的迭代器会抛出一个无效的迭代器exception。

使用STL,程序员使用iterators遍历容器,因为迭代器是一个抽象的概念,在所有的标准容器中实现。 例如, std::list根本没有operator []