[] : 空捕抓條款,表明 lambda body 不訪問閉合范圍(enclosing scope)的任何變量.
[&] : 以引用的方式訪問閉合范圍內的前面已聲明變量.
[=] : 以值的方式訪問閉合范圍內的前面已聲明的變量.
[this] : 訪問類實例的this指針.
auto y = [] (auto first, auto second)
{
return first + second;
};
– 轉換前的 lambda 條件:
1. 非泛型.
2. 沒有捕抓列表(即沒有捕抓任何變量)
– 轉換後的 函數
1. 同參數.
2. 相同返回類型.
3. 非虛擬
4. 非顯式常量.(non-explicit const)
vs2010
#include "stdafx.h"
#include
#include
#include
#include
#include
#include
#include
#include
class B
{
public:
B(int value):two("B")
{
one = value;
std::cout << "B" << std::endl;
}
~B(){two.clear(); std::cout << "~B" << std::endl;}
int one;
std::string two;
};
void TestSort()
{
std::cout << "TestSort" << std::endl;
// 2010也不支持快速枚舉. for(B* b: bs)
// 創建10個對象
std::vector bs(10);
int value = 0;
std::generate(bs.begin(),bs.end(),[&value]()->B*
{
B* b = new B(++value);
return b;
});
// 搜索奇數的對象
std::vector bs2;
std::for_each(bs.begin(),bs.end(),[&bs2](B* b)
{
if(b->one % 2)
{
bs2.push_back(b);
}
});
// 排序之前是升序.
std::cout << "Before Sort ==" << std::endl;
std::for_each(bs2.begin(),bs2.end(),[](B* b)
{
std::cout << b->one << std::endl;
});
// 降序排列
std::cout << "After Sort ==" << std::endl;
std::sort(bs2.begin(),bs2.end(),[](B* first,B* second)
{
return first->one > second->one;
});
std::for_each(bs2.begin(),bs2.end(),[](B* b)
{
std::cout << b->one << std::endl;
});
}
typedef void (*FUNC)();
void Foo(FUNC func)
{
func();
}
void TestLambdaAsync()
{
std::cout << "TestLambdaAsync ==" << std::endl;
//2010 不支持lambda轉換為FUNC,它只能用於template裡的實現;需要vs2012以上才支持.vs2010支持lambda到FUNC的轉換.
// 這樣就可以直接在 CreateThread裡使用 lambda.
//g++ 4.8.1 可以.
// Foo([](){std::cout << "lambda" << std::endl;});
// 錯誤 2 error C2664: “Foo”: 不能將參數 1 從“`anonymous-namespace'::”轉換為“FUNC”
}
void TestMutable()
{
std::cout << "TestMutable==========" << std::endl;
int m = 0;
int n = 0;
//去掉mutable會出現編譯錯誤.Error:表達式必須是可以修改的左值.
// mutable 作用之一就是省略掉本地變量的定義.
// [&, n] (int a){ int n1 = n; m = ++n1 + a; }(4);
[&, n] (int a)mutable{m = ++n + a; }(4);
std::cout << m << std::endl << n << std::endl;
}
class Base
{
public:
virtual ~Base() {}
virtual int call( float ) =0;
};
template< typename T>
class Eraser : public Base
{
public:
Eraser( T t ) : m_t(t) { }
int call( float f ) { return m_t(f); }
private:
T m_t;
};
class Erased
{
public:
template
Erased( T t ) : m_erased( new Eraser(t) ) { }
int do_call( float f )
{
return m_erased->call( f );
}
private:
Base* m_erased;
};
template
class A1
{
public:
A1(FUNC func):func_(func){}
void Run()
{
func_();
}
FUNC func_;
private:
};
Erased* GetErased()
{
int i = 9;
Erased *e_useful = new Erased( [i]( float f ) mutable ->int
{
std::cout << ++i << std::endl;
return 42;
} );
return e_useful;
}
int main(int argc, char const *argv[])
{
TestSort();
TestMutable();
int i = 0;
auto func1 = [i]()mutable
{
std::cout << "A: " << ++i << std::endl;
};
A1 a(func1);
a.Run();
Erased* e_useful = GetErased();
e_useful->do_call(9);
return 0;
}
輸出:
TestSort
B
B
B
B
B
B
B
B
B
B
Before Sort ==
1
3
5
7
9
After Sort ==
9
7
5
3
1
TestMutable==========
5
0
A: 1
10
gcc 4.8.1
// function_lambda_expression.cpp
// compile with: /EHsc /W4
#include
#include
#include
#include
#include
#include
#include
#include "pthread.h"
class A
{
public:
A()
{
std::cout << "A" << std::endl;
buf_ = (char*)malloc(6);
strcpy(buf_,"hello");
}
~A()
{
free(buf_);
buf_ = NULL;
std::cout << "~A" << std::endl;
}
char* buf_;
/* data */
};
// g++ 4.8.1 支持lambda函數到普通函數的轉換,但是有條件,不支持capture(推理)
// 查看C++14規范第6條款關於lambda表達式和普通C++函數的轉換關系.
// 傳遞共享指針,多線程共享變量例子.
void TestLambdaAsync(std::shared_ptr& a1)
{
std::cout << "Begin a1.use_count: " << a1.use_count() << std::endl;
pthread_t t1;
std::shared_ptr* a = new std::shared_ptr(a1);
std::cout << "After a1.use_count: " << a1.use_count() << std::endl;
// 如果是C函數指針作為參數,那麼lambda也不能捕抓任何變量,如[&a],不然會報錯.
// error: cannot convert 'TestLambdaAsync()::__lambda0' to 'void* (*)(void*)' for argument '3' to 'int pthread_create(pthread_t*, pthread_attr_t_* const*, void* (*)(void*), void*)'},NULL);
pthread_create(&t1,NULL,[](void* data)->void*
{
std::shared_ptr* a = reinterpret_cast
輸出:
Start ==
A
Begin a1.use_count: 1
After a1.use_count: 2
Begin a1.use_count: 2
After a1.use_count: 3
Begin a1.use_count: 3
After a1.use_count: 4
pthread_create: hello
Begin a1.use_count: 3
After a1.use_count: 4
pthread_create: hello
pthread_create: hello
Begin a1.use_count: 2
After a1.use_count: 3
pthread_create: hello
Begin a1.use_count: 3
After a1.use_count: 3
Begin a1.use_count: 3
After a1.use_count: 4
pthread_create: hello
Begin a1.use_count: 3
After a1.use_count: 4
pthread_create: hello
Begin a1.use_count: 3
After a1.use_count: 4
pthread_create: hello
pthread_create: hello
Begin a1.use_count: 2
After a1.use_count: 3
pthread_create: hello
Sleep
pthread_create: hello
Exit ==
~A