迭代容器的最佳方法

时间:2009-01-31 07:40:13

标签: c++ iterator containers

这两种迭代容器的方法有哪些优点/缺点/您喜欢哪种方式以及原因:

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

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

附属问题:i ++或++ i?为什么呢?

7 个答案:

答案 0 :(得分:5)

如果迭代器是非平凡的(即不是指针),++ i肯定更快,因为它不涉及复制到临时,可能会也可能不会被优化。

第一种形式有点快,但如果你在循环中删除或插入东西,可能会出错。

对于容器上的简单迭代,我使用

#define foreach BOOST_FOREACH // in some header

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

大部分时间都是简洁明了。

答案 1 :(得分:3)

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

答案 2 :(得分:2)

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

类似于++ i vs i ++,当迭代器是一个复杂的类(而不仅仅是stl迭代器中的指针)时,我可能是一个更昂贵的操作,而i ++正在发生的事情是它正在递增迭代器但是在它之前的状态中返回迭代器的副本。 for ++ i它返回迭代器的当前状态,所以只能返回对它自己的引用。

通常最好只在您的探查器确定存在问题时优化您的代码 - 最好保持代码尽可能易读。

答案 3 :(得分:1)

我实际上总是做第二个,尽管我有时会担心如果多次调用会减慢事情的速度。我认为这会被优化,但肯定不知道。

而且我肯定是。它永远不会比i ++慢,如果它更快的话。

答案 4 :(得分: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 指出,这不适用于一半标准容器,例如listmap。实际上,那些需要使用适当的迭代器。相关地,在编写通用代码时应始终使用iterator

答案 5 :(得分:0)

Boost.Foreach介绍了一个不错的方法:

#define foreach         BOOST_FOREACH
// ...
Container<Item> container;
// ...
foreach (Item item, container) {
  // do some stuff with the item
}

答案 6 :(得分:0)

对于容器中的每个元素,C ++“循环是最有效的,而上下文不会调用迭代逻辑。

$a = Import-Csv .\users_pass.csv |
     Select-Object "User Name", Passphrase |
     Foreach-Object {
         $user = $_
         $aduser = Get-ADUser -Filter "SamAccountName -like '*$($_."User Name")*'" -Properties EmailAddress |
                   select EmailAddress

         New-Object -TypeName PSObject -Property @{
             Username = $user."User Name"
             Passphrase = $user.Passphrase
             EmailAddress = $aduser.EmailAddress
         }
     }