自己的闭包,自动从环境中俘获了sum和step,若用class实现,上面的程序起码增加10行代码。
?
?
?
LB性能初探
下面的简单程序,测试四种功能完全一样,但使用不同表达式的逻辑:
?
1)t =1 时用LB,
?
2)t=2 时用直接表达式
?
3)t=3 时用函数
?
4)t=4时用std::function间接调用LB
?
?
?
void TestLambdaFun(int t)
?
{
?
? ? ? ?using namespace std;
?
? ? ? ?vector v1(10, 1);
?
? ? ? ?int x = 0;
?
? ? ? ?int u = 0;
?
? ? ? ?if (t == 1)
?
? ? ? ?{
?
? ? ? ? ? ? ?clock_t begin = clock();
?
? ? ? ? ? ? ?for (int i = 0; i < 100000; ++i)
?
? ? ? ? ? ? ?{
?
? ? ? ? ? ? ? ? ? ? for_each (v1.begin(),
?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? v1.end(),
?
? ? ? ? ? ? ? ? ? ? ? ? ? [&x, &u](int i){ u += i+(x++); });// Line 1
?
? ? ? ? ? ? ?}
?
? ? ? ? ? ? ?clock_t end = clock();
?
? ? ? ? ? ? ?auto spent = double(end - begin) / CLOCKS_PER_SEC;
?
? ? ? ? ? ? ?printf("spent for type '%d' is %f u is %d\n", t, spent, u);
?
? ? ? ?}
?
? ? ? ?else if (t == 2)
?
? ? ? ?{
?
? ? ? ? ? ? ?clock_t begin = clock();
?
? ? ? ? ? ? ?for (int i = 0; i < 100000; ++i)
?
? ? ? ? ? ? ?{
?
? ? ? ? ? ? ? ? ? ? auto _First = v1.begin();
?
? ? ? ? ? ? ? ? ? ? auto _Last = v1.end();
?
? ? ? ? ? ? ? ? ? ? for (; _First != _Last; ++_First)
?
? ? ? ? ? ? ? ? ? ? {
?
? ? ? ? ? ? ? ? ? ? ? ? ? ?u = *_First+(x++); ? ? ? ? ? ? ? ? ?// Line 2
?
? ? ? ? ? ? ? ? ? ? }
?
? ? ? ? ? ? ?}
?
? ? ? ? ? ? ?clock_t end = clock();
?
? ? ? ? ? ? ?auto spent = double(end - begin) / CLOCKS_PER_SEC;
?
? ? ? ? ? ? ?printf("spent for type '%d' is %f u is %d\n", t, spent, u);
?
? ? ? ?}
?
? ? ? ?else if (t == 3)
?
? ? ? ?{
?
? ? ? ? ? ? ?clock_t begin = clock();
?
? ? ? ? ? ? ?for (int i = 0; i < 100000; ++i)
?
? ? ? ? ? ? ?{
?
? ? ? ? ? ? ? ? ? ? auto _First = v1.begin();
?
? ? ? ? ? ? ? ? ? ? auto _Last = v1.end();
?
? ? ? ? ? ? ? ? ? ? for (; _First != _Last; ++_First)
?
? ? ? ? ? ? ? ? ? ? {
?
? ? ? ? ? ? ? ? ? ? ? ? ? ?FuncAdd(u, x, *_First); ? ? ? ? ? ? // Line 3
?
? ? ? ? ? ? ? ? ? ? }
?
? ? ? ? ? ? ?}
?
? ? ? ? ? ? ?clock_t end = clock();
?
? ? ? ? ? ? ?auto spent = double(end - begin) / CLOCKS_PER_SEC;
?
? ? ? ? ? ? ?printf("spent for type '%d' is %f u is %d\n", t, spent, u);
?
? ? ? ?}
?
? ? ? else if (t == 4)
?
? ? ? ?{
?
? ? ? ? ? ? ? clock_t begin = clock();
?
? ? ? ? ? ? ? std::function lbda;
?
? ? ? ? ? ? ? for (int i = 0; i < 100000; ++i)
?
? ? ? ? ? ? ? {
?
? ? ? ? ? ? ? ? ? ? lbda = [&](int i){ u += i + (x++); };
?
? ? ? ? ? ? ? ? ? ? for_each (v1.begin(), v1.end(), lbda); // Line 4
?
? ? ? ? ? ? ? }
?
? ? ? ? ? ? ? clock_t end = clock();
?
? ? ? ? ? ? ? auto spent = double(end - begin) / CLOCKS_PER_SEC;
?
? ? ? ? ? ? ? printf("spent for type '%d' is %f u is %d\n", t, spent, u);
?
? ? ? ?}
?
?
?
}
?
?
?
void FuncAdd(int &u, int &x, int i)
?
{
?
? ? ? ?u = i+(x++);
?
}
?
?
?
?
?
?
在debug模式下,t=2时速度最快,这是因为t=1,t=3,t=4时都是用了函数调用,性能当然不及inline表达式。
在release模式下(选择/Ob1优化,对inline函数进行inline扩展)
t=1和t=2速度完全一样,比t=3时平均快3倍。当然,我们也可以把FuncAdd inline化。这里的主要目的,是证明优化后,LB的性能和表达式完全一样。证明
C++ lambda expression不是浪得虚名的隐身类的syntax sugar,而是名副其实的“表达式”。
t=4最慢,它和t=3类似。但是由于通过了std::function的虚拟函数表间接调用,/Ob1优化失去作用,使它不但要调用一个() operator,而且是通过“虚拟表”间接调用。所以从性能上说,把LB通过std::function间接使用,失去了LB的性能优势。