【问题标题】:Would Iterator loop call end() for many times?迭代器循环会多次调用 end() 吗?
【发布时间】:2016-11-10 17:09:23
【问题描述】:
#include <vector>
#include <iostream>

class Range {
    typedef typename std::vector<int> Vec;
    typedef typename Vec::iterator Iterator;
public:
    Range(Vec& vec, const int start_id, const int size)
            : vec_{vec},
              it_begin_{vec_.begin() + start_id},
              it_end_  {vec_.begin() + start_id + size}
    {}
    Iterator& begin() {return it_begin_;}
    Iterator& end()   {return it_end_;}
private:
    Vec& vec_;
    Iterator it_begin_;
    Iterator it_end_;
};

int main()
{
    std::vector<int> a;
    a.resize(100);
    Range range(a,0,10);
    for (auto it = range.begin(); it != range.end(); ++it) { // Line A
        std::cout << it - range.begin() << "\n"; // Line B
    }
}

Assembly here

假设我使用优化(如g++ -Ofast)。

在 A 行,程序是否会多次调用range.end(),而不是保存 range.end() 的值并在循环的每次迭代中与该值进行比较?

在 B 行,程序是否会多次调用range.begin(),而不是为整个循环保存range.begin() 的值,然后在循环的每次迭代中从中减去该值?

【问题讨论】:

  • 为什么不编译并检查程序集?
  • 呃。我以为每个人都会知道……(除了我不知道)。

标签: c++ loops iterator


【解决方案1】:

在您的代码中,优化器可以看到begin()end() 的实现。它可以内联它们,并将不变量提升到循环之外。

如果begin()end()main() 在不同的翻译单元中,答案可能会有所不同,因为链接时间对于此类优化通常为时已晚。

【讨论】:

    【解决方案2】:

    很难预测优化器在给定的优化级别上会做什么和不会做什么。虽然这种特殊的转换是微不足道的,并且通常在允许内联时完成,但不能保证。

    如果有疑问,我会遵循古老的俄语谚语,大致翻译为“相信优化器,但不要自己做傻瓜!”。所以我会使用一个 const 变量来存储调用的结果。它将首先使代码更具可读性,并且作为一个很好的副作用,它可能会帮助一些自相矛盾的优化器。一个好的优化器无论如何都会消除这个变量。

    【讨论】:

    • 在这里,我想我们称之为“信任,但要验证”。
    【解决方案3】:

    .end() 成员的访问具有恒定的复杂性,它被读取一次并用作循环中的限制。您可以查看this 示例以获取map 容器,但它也适用于其他容器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-14
      • 1970-01-01
      • 1970-01-01
      • 2014-10-11
      • 2020-02-16
      相关资源
      最近更新 更多