我通常会与其他人讨论并且我无法确认行为 - 如果内联的是container.end()和container.size()函数。对于例如如果我们有这样的for循环:
for (vector<int>::iterator it=v.begin(); it!=v.end(); ++it) {
//...
}
for (size_t k=0; k < v.size(); ++k) {
//...
}
在上述情况下,将重复调用v.end()和v.size()函数或
答案 0 :(得分:2)
所有模板函数都是内联函数。编译器可以选择使它们成为可调用函数,特别是如果它是调试模式编译,但最可能的结果是内联代码。
可能但不太可能自动创建临时变量。编译器如何确定v.end()或v.size()返回值是否会受到循环中代码的影响?我怀疑大多数人都不打扰,虽然我也没有任何证据。
答案 1 :(得分:1)
即使函数是内联的,如果嵌套代码足够大/复杂,也不能指望编译器正确优化循环。这是因为语义,你可能不希望end()
值在循环的每次迭代中都改变,所以它应该只计算一次。但是,编译器可能无法基于别名注意事项和优化器中的其他“放弃”条件来进行保证。如果 - 像其他海报一样已经回答 - 您预先计算end()
并将其存储在变量中,编译器就不太可能感到困惑。
例如:
typedef std::vector<int> intvec;
intvec v = external_function();
for (intvec::const_iterator vi = v.begin(); vi != v.end(); ++vi) {
call_external_function(v, *vi);
}
从编译器的角度来看,call_external_function()
可能会改变向量的大小。如果您知道不可能发生这种情况,那么您应该告诉编译器:
for (intvec::const_iterator vi = v.begin(), ve = v.end(); vi != ve; ++vi) {
call_external_function(v, *vi);
}
答案 2 :(得分:0)
尽管模板函数是内联的,但很难说编译器会提供我们需要的相同程度的优化。 可以使用以下技术。
将v.end()
存储在临时vEnd
:
for(vector<TYPE>::iterator it = v.begin(), vEnd = v.end(); it != vEnd; it++) {}
反向执行循环:
for (size_t k = v.size() - 1; k != (size_t)(-1) ; --k) { }