lambda表达式一般是,编译器编译成lambda_xxxxxxxxxx这样类。由于xxxxxxxxxx是随机生成的,所以你一般永远无法事先知道这个类的类名,下面写集中情况来分析。
1.不捕获外部变量
int a = 10;
void (*fun)(int& a);
[](int& a){
printf("%d", a);
};
当你这样写时,不捕获外部变量,就相当于外部生成了一个 ’void lambda_xxxxxxxxxx::operator()(int& a)
的函数。由于这个类未捕获任何数据,所以类大概是这样的:
class lambda_xxxxxxxxxx
{
public:
void operator()(int& a);
private:
};
void lambda_xxxxxxxxxx::operator()(int& a) {
printf("%d", a);
}
这个类就这样,大小为1字节;
改写调用时情况:
int a = 10;
void (*fun)(int& a);
[](int& a){
printf("%d", a);
}(a);
相当于这样:
lambda_xxxxxxxxxx()(a);
这里直接生成匿名对象,并调用lambda_xxxxxxxxxx::operator()(int& a)
,很像仿函数吧
2.捕获外部变量的情况
下面在说另一种情况:捕获外部变量时:
int a = 10;
int b = 30;
void (*fun)(int& a);
[&b](int& a){
printf("%d", a);
};
这个类大概是这样的:
class lambda_xxxxxxxxxx
{
public:
lambda_xxxxxxxxxx(int& a);
void operator()(int& a);
private:
int* b;
};
lambda_xxxxxxxxxx::lambda_xxxxxxxxxx(int& a) :b(&a) {
}
void lambda_xxxxxxxxxx::operator()(int& a) {
printf("%d", a);
}
这个类的调用过程是:
int a = 10;
int b = 30;
void (*fun)(int& a);
lambda_xxxxxxxxxx(b);
直接用有参构造生lambda_xxxxxxxxxx::lambda_xxxxxxxxxx(int& a) :b(&a)
成一个匿名对象,但未调用lambda_xxxxxxxxxx::operator()(int& a)
;所以你直接用函数指针去接是不对的,构函数是没有返回值的。所以编译器判定你这个写法有问题;
在写一个调用的情况:
int a = 10;
int b = 30;
void (*fun)(int& a);
[&b](int& a){
printf("%d", a);
}(a);
生成的类是和捕获外部变量,没调用的类一样的;
调用过程:
int a = 10;
int b = 30;
void (*fun)(int& a);
lambda_xxxxxxxxxx(b)(a);
这里是先调用有参构造lambda_xxxxxxxxxx::lambda_xxxxxxxxxx(int& a) :b(&a)
,生成匿名对象,顺手调用了lambda_xxxxxxxxxx::operator()(int& a)
;
最后
当你这样写的
int a = 10;
int b = 30;
void (*fun)(int& a);
fun = [](int& a){
printf("%d", a);
};
就相当于
int a = 10;
int b = 30;
void (*fun)(int& a);
fun = lambda_xxxxxxxxxx::operator()(int& a)
很明显编译认为对的,没有什么语法错误;
当你捕获时:
int a = 10;
int b = 30;
void (*fun)(int& a);
fun = [&b](int& a){
printf("%d", a);
};
相当于:
int a = 10;
int b = 30;
void (*fun)(int& a);
fun = lambda_xxxxxxxxxx::lambda_xxxxxxxxxx(int& a) :b(&a);
析构没有返回值,此时还产生了一个匿名对象。
和iOS的block对比,
虽然两者都很像,但是iOS产生的是一个结构体,基本也算一个类;
总结下
相同点:
1.都是各一个类(虽然block是一个结构体,结构体也可以认为是一个类)
2.写法很相同
3.都能捕获外部变量,
4.都可以通过自己的方法,改写外部变量
不同点:
1.lambda是在栈上的匿名对象。block是在堆上的(现在的block都是在堆上的)
2.lambda无法再捕获外部变量的情况下,用函数指针接,而block可以(runtime自己找)
总之,block比lambda强大一些
以上lambda的两种情况都是反汇编得知的
网友评论