Lambda表达式
Lambda表达式,简称Lambda,是C++11标准的新特性。Lambda是定义匿名函数对象(function object)的简便方式,通常作为参数传递给算法或异步方法。本文讨论如何传递Lambda到含有函数指针类型参数的函数。
有关Lambda Expression的详细内容,请参考:Lambda Expressions in C++
有关Function Object的详细内容,请参考:Function Objects in the C++ Standard Library
回调函数
考虑Unix系统一个创建线程的API:
int pthread_create(pthread_t* thread,
const pthread_attr_t* attr,
void* (*start_routine)(void*),
void* arg)
pthread_create创建新的线程,新线程从回调函数指针start_routine指向的函数开始执行,第四个参数arg是传递给回调函数的参数。为了便于讨论和编写演示代码,先设计下面这个函数:
void do_work(void (*work_routine)(void*), void* arg)
{
cout << "begin work" << endl;
work_routine(arg);
cout << "end work" << endl;
}
do_work与pthread_create类似,有一个回调函数指针参数和传递给回调函数的void*参数。如果回调函数需要多个参数,可以用结构体存放这些参数。参考下面的示例代码:
// 连接字符串s1和s2,结果存入s3
struct string_join_args
{
const char* s1;
const char* s2;
string& s3;
};
void string_join_routine(void* arg)
{
string_join_args* args = (string_join_args*)arg;
args->s3 = args->s1;
args->s3 += args->s2;
}
void example1()
{
const char* s1 = "example1_s1_";
const char* s2 = "s2";
string s3;
string_join_args args = {
s1, s2, s3 };
do_work(string_join_routine, &args);
cout << "s3 : " << s3 << endl;
}
绑定Lambda表达式到回调函数
上面的代码繁琐,可读性差。如果可以向do_work传递Lambda表达式,那么代码会变得简洁和易于阅读,像下面这样:
do_work([=, &s3](){
s3 = s1;
s3 += s2;
}, ...);
除了函数指针和成员指针, void*能与其它任何类型的指针相互转换。因此可以向void*参数传递Lambda指针或Lambda包装器指针,并编写相应的回调函数调用Lambda,以实现上述效果。
方案一:向void*参数传递Lambda指针
如果向函数的void*参数传递Lambda指针并在函数中调用此Lambda,必须显示地转换void*为它实际所指向的Lambda类型的指针。下面的示例代码演示void*和Lambda指针的相互转换:
void example2()
{
int x = 2;
auto lambda = [x](int y) {
return x + y;
};
void* pv = λ // Lambda指针转换成void*
auto lambdaptr = static_cast<