#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
}
}
假设我使用优化(例如g++ -Ofast
)。
在A行中,程序会多次调用range.end()
,而不是保存range.end()的值,并在循环的每次迭代中将该值与它进行比较吗?
在B行中,程序会多次调用range.begin()
,而不是为整个循环保存range.begin()
的值,然后在循环的每次迭代中从中减去该值吗? / p>
答案 0 :(得分:3)
在您的代码中,优化程序可以查看LeftMenuTableView
和begin()
的实现。它可以内联它们,并将不变量提升到循环之外。
如果end()
和begin()
位于与end()
不同的翻译单元中,答案可能会有所不同,因为此类优化的链接时间通常为时已晚。
答案 1 :(得分:3)
很难预测优化器在给定的优化级别上会做什么和不会做什么。虽然这种特殊的转换是微不足道的,并且通常在允许内联时进行,但不能保证。
如果有疑问,我会遵循古老的俄语说法,松散地翻译为“对优化器有信心,但不要自己做假!”#39;。所以我会使用const变量来存储调用的结果。它首先会使代码更具可读性,并且作为一个很好的副作用,它可能会帮助一些自相矛盾的优化器。一个好的优化器无论如何都会消除变量。
答案 2 :(得分:1)
.end()
成员的访问具有不变的复杂性,它被读取一次并被用作循环中的限制。您可以查看map
容器的this示例,但它也适用于其他容器。