已经回答得很好,但我会添加我的 S/0.02:“正确”的方法是:
for (typename std::vector<MyObject>::size_type i = 0; i < object.size(); ++i) { ... }
只有有抱负的语言律师才会这样写,甚至他们也可能在读到好东西之前就停止阅读。
使用 C++11,您可以利用decltype
:
for (decltype(object.size()) i = 0; i < object.size(); ++i) { ... }
或者您可以利用auto
:
for (auto i = object.size() - object.size(); i < object.size(); ++i) { ... }
或者您可以只使用size_t
,但您仍然可能对溢出有疑问,因为vector<MyObject>
的 size_type 可能大于 size_t。(不是,但不能保证):
for (size_t i = 0; i < object.size(); ++i) { ... }
那么,一个诚实的程序员应该做什么呢?
最简单的解决方案是 STL 从一开始就一直在推广的解决方案。除了一开始,写起来也很痛苦:
for (typename std::vector<MyObject>::iterator_type it = object.begin(); it != object.end(); ++it) { ... }
现在,C++11 确实对您有所帮助。你有一些非常好的选择,从简单的开始:
for (auto it = object.begin(); it != object.end(); ++it) { ... }
但它变得更好(鼓,请)......:
for (auto& val : object) { ... }
这就是我会使用的那个。
编辑添加:
Cory Nelson 在评论中指出,还可以通过以下方式缓存 object.end() 的结果:
for (auto it = object.begin(), end = object.end(); it != end; ++it) { ... }
事实证明,该for (var : object)
语法生成的代码与 Cory Nelson 提出的代码非常相似。(所以我鼓励他和你只使用后者。)
但是,这与其他语义有细微的不同,包括作为原始帖子主题的迭代。如果您在迭代期间以改变其大小的方式修改容器,那么您必须非常仔细地考虑问题。灾难的可能性很大。
迭代可能在迭代期间被修改的向量的唯一方法是使用整数索引,如原始帖子中所示。其他容器更宽容。您可以使用在每次迭代时调用 object.end() 的循环来迭代 STL 映射,并且(据我所知)即使面对插入和删除它也可以工作,但不要尝试使用 unordered_map,或向量。如果你总是在最后推并在前面弹出,它确实适用于双端队列,如果你在广度优先步行中使用双端队列作为队列,这很方便;我不确定你是否可以在后面弹出双端队列。
确实应该有一个简单的总结容器类型对迭代器和元素指针(它们并不总是与迭代器相同)的容器修改的影响,因为这都是由标准指定的,但我从来没有遇到过任何地方。如果你找到了,请告诉我。