1

这两种迭代容器的方法的优点/缺点是什么/您更喜欢哪一种以及为什么:

for (MyClass::iterator i = m.begin(), e = m.end() ; i != e ; i++)
{
    // ...
}

或者

for (MyClass::iterator i = m.begin() ; i != m.end() ; i++)
{
    // ...
}

附属问题:i++ 还是 ++i?为什么?

4

7 回答 7

5

If the iterator is non-trivial (ie. not a pointer), ++i is definitely faster as it doesn't involves a copy to a temporary, which may or may not be optimized out.

The first form is a little faster but could be wrong if you erase or insert things in the loop.

For simple iteration over a container I use

#define foreach BOOST_FOREACH // in some header

foreach(MyType &element, any_container) {
  // deal with element
}

most of the time for succinctness and clarity.

于 2009-01-31T08:09:26.910 回答
3

除非您关闭了优化,否则两者都是等效的。至于 i++ 或 ++i,++i 效率更高,因为它不涉及临时值。

于 2009-01-31T07:47:02.090 回答
2

对于普通的 stl 迭代器,没有太大的区别,但是如果你的集合很复杂并且要求 end 很昂贵,那么只要求 end 一次可能会更快。

同样,对于 ++i 与 i++,当迭代器是一个复杂的类(而不仅仅是 stl 迭代器中的指针)时,++i 可能是一个更昂贵的操作,而 i++ 发生的是它正在递增迭代器但返回一个副本迭代器处于其先前状态。对于 ++i 它以当前状态返回迭代器,因此可以只返回对自身的引用。

通常最好只在探查器发现存在问题时才优化代码——最好让代码尽可能易于阅读。

于 2009-01-31T07:57:52.677 回答
1

实际上,我总是做第二个,尽管有时我确实担心多次调用 end 会减慢速度。我的印象是这会被优化,但不确定。

并且 ++i 绝对是。它永远不会比 i++ 慢,如果有的话,它会更快。

于 2009-01-31T07:52:08.663 回答
1

第一个更快,因为end()不是每次迭代都调用。不,优化器不能轻易地为你缓存它,因为它不知道容器的大小在这次迭代中是否发生了变化(因此最终移动了)。由于别名问题,这也适用于 const 容器。

i++返回 i 的副本,然后递增。++i递增,然后返回递增的值。因此,当您丢弃返回值时,请使用它,++i因为它需要做的工作更少(不复制)。优化器很可能会修复内联i++调用,因此它的速度与它一样快,++i但不要依赖它。

我?我用

for(int i = 0; i < m.size(); i++) {
    // ... do something with m[i]
}

因为它是最短最清晰的。为什么int而不是MyClass::size_type?因为它更简单,到目前为止我从来不用担心边缘情况。为什么i++?因为对于基本类型,它总是被优化为++i,并且它对同事来说不那么混乱。作为奖励,我也可以将i其用作数值。使用迭代器,我必须保留一个单独的计数器,或者使用std::distance.

obecalp指出,这不适用于一半的标准容器,例如listand map。事实上,那些需要使用适当的迭代器。iterator相关地,在编写通用代码时,您应该始终使用 an 。

于 2009-01-31T07:54:00.343 回答
1

The C++ "for every element in container" loop is the most efficient where the context doesn't call for iterative logic.

for(Item& i : Container)
{
     dosomething(i);
}

or

for(const Item& i : Container)
{
     dosomething(i);
}
于 2016-11-18T21:26:57.810 回答
0

Boost.Foreach introduces a nice way:

#define foreach         BOOST_FOREACH
// ...
Container<Item> container;
// ...
foreach (Item item, container) {
  // do some stuff with the item
}
于 2009-01-31T08:16:16.977 回答