container.end()和container.size()是否内联?

时间:2011-04-10 23:43:09

标签: c++ performance containers inline

我通常会与其他人讨论并且我无法确认行为 - 如果内联的是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()函数或

  1. 将编译内联这些函数
  2. 将由编译器
  3. 创建临时变量
  4. 优化选项O1..3会影响g ++中的行为吗?

3 个答案:

答案 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) { }