【问题标题】:Iterating Vector/Map data structure C++迭代向量/映射数据结构 C++
【发布时间】:2011-02-15 16:05:20
【问题描述】:

这些天我一直在广泛使用地图/矢量,但对迭代它们有疑问

哪个更好?

for(vector<string>::iterator it=myvec.begin(); it!=myvec.end(); ++it){
}

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

首先,他们是否打算做同样的事情?

【问题讨论】:

  • 什么更好?您想如何访问容器的元素?
  • 我只想按任意顺序访问元素
  • 您无法访问索引为 int 的地图
  • 抱歉,已编辑。实际上想访问向量,但最终使用了地图

标签: c++ vector map


【解决方案1】:

对于遍历向量,两者都同样适用。我偏爱迭代器,因为我见过用索引做的坏事——主要是有人使用一个容器的索引来访问另一个容器。如果第二个容器更小,这将不起作用。

如果你只是想为每个元素做一些事情,你可以使用BOOST_FOREACH

std::list<int> list_int( /*...*/ );
BOOST_FOREACH( int i, list_int )
{
    // do something with i
}

【讨论】:

  • @Ringo - 这取决于实现。给定未经检查的迭代器和良好的编译器,它们可能对于向量是相同的,是的。
【解决方案2】:

当你使用 manual 循环时,它并没有太大的区别。但是当您使用 STL 函数(比如来自 &lt;algorithm&gt; 的函数)时,您别无选择。您必须使用迭代器,因为 STL 函数使用迭代器,而不是索引。

例如,如果您想使用 std::accumulate 计算 vector&lt;int&gt; 中所有整数的总和,那么您必须这样做:

 int sum = std::accumulate(vints.begin(),vints.end(),0);

所以我的建议是:养成使用迭代器的习惯,因为它给你统一性,也逐渐让你对迭代器的哲学感到满意。它给人一种笼统的感觉!

【讨论】:

  • @Ringo:实际上不是。如果你看到了,迭代器比索引提供更多的通用性。所以迭代器应该是首选,即使是手动循环,只是为了统一。好吧,这也与味道有关。很好,您可以将索引与手动循环一起使用。 :-)
  • 迭代器是对索引或指针访问的抽象。如果您需要该抽象,请使用它!如果容器是向量类型,上面的示例也适用于指针。但是,如果您将容器类型从向量更改为映射,那么迭代器是更好的选择:)。所以...这取决于...
【解决方案3】:

这取决于您在执行循环主体时是否需要知道元素在其容器中的位置。如果这样做,则需要使用第二种形式。如果没有,请使用第一个,因为它更通用,因此更灵活;您可以将 myvec 的类型更改为任何支持迭代器的类型,即使它不支持随机访问。

【讨论】:

    【解决方案4】:

    来自 Meyers “Effective STL”,第 43 条。

    “比手写循环更喜欢算法调用”

    • 算法通常比程序员产生的循环更有效
    • 编写循环更容易出错
    • 算法代码更易阅读

    尽可能多地使用带有迭代器的算法。

    std::for_each(myvec.begin(), myvec.end(), [](const string& s) {
       /* your code here */
    });
    

    【讨论】:

      【解决方案5】:

      我尽量隐藏容器的底层实现。

      所以在你的例子中,我会先使用 typedef 而不是直接引用向量(稍后你会明白为什么):

      typedef std::vector<string> MyStringCollection;
      

      然后,我尝试使用尽可能少依赖底层实现的结构。在这种情况下,我想遍历容器并使用容器中的值,如下所示:

      for(MyStringCollection::iterator it=mycollection.begin(); it!=mycollection.end(); ++it)
         {
         // use *it
         } 
      

      使用 typedef,您的集合的用户只需使用 MyStringCollection::iterator 而无需知道 MyStringCollection 实际上是什么。

      请注意,在 C++0x 中,您可以使用 auto,它甚至更短(使我对 typedef 的论证不太相关)。

      这样做的好处是现在将 MyStringCollection 从 std::vector 更改为 std::list 变得非常容易。如果由于性能原因您认为列表更适合,您只需:

      • 将 typedef 从 std::vector 更改为 std::list
      • 快速浏览所有使用 MyStringCollection 的地方(这比查找 std::vector 的所有用途更容易找到

      【讨论】:

        猜你喜欢
        • 2011-02-09
        • 1970-01-01
        • 2015-02-19
        • 1970-01-01
        • 1970-01-01
        • 2013-01-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多