一篇极好的文章,建议直接转到 https://shaharmike.com/cpp/lambdas-and-functions/
然后...再多说一点,lambda表达式只要没有最后表示执行的括号,其实就是一个对象,如下
int main()
{
int a;
int b;
char c;
char d;
auto func = [&a, b, &c, d ](int i, int j){std::cout << i+j << std::endl;};
// 错误,func不是一个函数指针
void (*q)();
q = func;
// 正确,将void类型指针指向func对象地址并调用,结果输出3
void* p = &func
(*p)(1, 2);
}
[...] 中捕获的变量或者引用其实是对象中的成员变量(引用会成为成员变量吗?经测试得到引用被捕获之后占用空间大小表现为指针的特性),测试如下。
int main()
{
int a;
int b;
char c;
char d;
auto func = [&a, b, &c, d](int i, int j){};
std::cout << sizeof(func) << std::endl;
}
// 输出结果是32
int main()
{
int a;
int b;
char c;
char d;
auto func = [a, b, &c, d](int i, int j){};
std::cout << sizeof(func) << std::endl;
}
// 输出结果是24
int main()
{
int a;
int b;
char c;
char d;
auto func = [c, d, a, b](int i, int j){};
std::cout << sizeof(func) << std::endl;
}
// 输出结果是12
由此可以看出,lambda对象中成员变量的内存布局(引用变量表现为指针),其实是按照普通结构体字节码对其的规则划分的。
我的一个猜测:lambda表达式捕获的变量或者引用只能具有局部生命周期(也就是说只能捕获函数里面的局部变量),因此lambda表达式的对象在是在函数里面实例化的(也就是存在于在栈内存中),而lambda表达式传入的参数也是在栈上,所以lambda表达式捕获的变量和给它传入的参数在同一块存储区域内。