范围循环的c ++比递减循环更快

时间:2014-10-08 13:54:20

标签: c++ performance c++11 for-loop

我们经常以这种方式从最后一个元素开始循环遍历数组:

static const char* pszStrings[] = { ... }
for (size_t i = _countof(pszStrings); i--;)
    use(pszStrings[i]);

我的问题是,如果基于for循环的新范围同样有效且可以使用:

static const char* pszStrings[] = { ... }
for (auto string : pszStrings)
    use(string);

另外......

由于我无法查看生成的代码,即使我不知道,如果我能够做出正确的结论,我也会这样做。我会很高兴没有太科学的答案!

1 个答案:

答案 0 :(得分:5)

编译器可以对新range for-loop中的迭代集合做出很多假设,即先前编写的for循环中的迭代集合。例如:

在C ++ 98天通常写一次:

for (std::vector<int>::const_iterator it = v.begin(), it_end = v.end(); 
     it != it_end; ++it) {
    // code ..
}

使用it_end是因为在很多情况下,编译器无法确定集合是否会在for-loop中改变大小(并且.end()可能会更改)。如果你写:

for (std::vector<int>::const_iterator it = v.begin(); it != v.end(); ++it) {
    // code ..
}

编译器可以在每次执行循环时生成对.end()函数的调用。

range for-loop与旧的for循环一样有效(效率提高一倍)。

一些例子:

如果你有一个循环迭代std::vector索引:for (int i = 0; i < v.size(); ++i)这个循环需要索引向量以使用元素(v[i])最肯定不是明显的等待,但是当矢量真的很大时,可以注意到紧密的循环。

更新为range for-loop时,这种循环会有所改善。

答案中的第一个循环最有可能不会提高性能,但是在清晰度上,代码的读者会知道代码是为了迭代所有集合而不是跳过一些元素(以旧的方式,你可以识别for循环中的for-each pattern,但它很乏味并且可能导致错误的结论(可能在正文中正在修改索引或迭代器)关于代码如果不小心。