一篇極好的文章,建議直接轉到 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表達式捕獲的變量和給它傳入的參數在同一塊存儲區域內。