Iterator循环调用end()多次?

时间:2016-11-10 17:09:24

标签: c++ loops iterator

#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()的值,然后在循环的每次迭代中从中减去该值吗? / p>

3 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:3)

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

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

答案 2 :(得分:1)

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