我正在测试以下代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
int main(int argc, char* argv[])
{
std::vector<int> v(10000000);
clock_t then = clock();
if(argc <= 1)
std::for_each(v.begin(), v.end(), [](int& it){ it = 10098; });
else
for(auto it = v.begin(); it != v.end(); ++it) *it = 98775;
std::cout << clock() - then << "\n";
return 0;
}
我用g ++ 4.6编译它,没有任何优化标志,这就是我得到的:
[javadyan@myhost experiments]$ ./a.out
260000
[javadyan@myhost experiments]$ ./a.out aaa
330000
[javadyan@myhost experiments]$
使用-O1优化会产生以下(不足为奇)的结果:
[javadyan@myhost experiments]$ ./a.out
20000
[javadyan@myhost experiments]$ ./a.out aaa
20000
我在双核2Ghz笔记本电脑上运行Linux 3.0,如果这很重要的话。
我想知道的是,在没有任何优化的情况下编译的程序中,如何使用lambda函数调用for_each可以比普通的for循环少吃掉时钟?调用匿名函数不应该有轻微的开销吗?有没有关于代码如何
的文档 std::for_each(v.begin(), v.end(), [](int& it){ it = 10098; });
由g ++处理?在这种情况下,其他流行编译器的行为是什么?
更新
我没有考虑第二个表达式中的it
在每次迭代时都与v.end()
进行比较的事实。通过修复,for循环比for_each节省更少的时钟。但是,我仍然很好奇编译器在使用-O1标志时如何优化for_each。
答案 0 :(得分:7)
乍一看,我至少可以说那些表达方式并不相同。请尝试使用此功能:
for(auto it = v.begin(), end = v.end(); it != end; ++it) *it = 98775;
此外,由于lambda的确切类型传递给for_each
,编译器很可能会内联它,导致代码与for循环没有区别。请注意,匿名函数中不涉及虚拟调用。编译器将执行以下操作:
class __lambda_function_123
{
public:
void operator()(int& it) const{ it = 10098; }
};
std::for_each(v.begin(), v.end(), __lambda_function_123());
除了内联之外,将产生与for循环完全相同的代码(包含我的修改)。
答案 1 :(得分:0)
有趣的是,即使在制作了“end = v.end(),i!= end”优化之后,你的for_each&amp;在调试模式下,Visual Studio 2010中的lambda case仍然运行得更快。
在VS2010中使其更快的一个优化是,元模板机制可以检测向量迭代器的使用并切换到使用原始指针到开始/结束的整数,这在调试模式期间消除了大量的验证检查operator ++,operator *和operator!=。