初始化捕獲
上一篇講到 c++ 11 可以支援 Lambda 捕獲變量,看 code 回顧一下,而且改寫一下故意把變數名稱寫的很長。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
int main() {
int x_thisIsAnExtremelyLongVariableName = 10;
int y_thisIsAnExtremelyLongVariableName = 20;
auto addXY = [x_thisIsAnExtremelyLongVariableName, y_thisIsAnExtremelyLongVariableName]() -> int {
return x_thisIsAnExtremelyLongVariableName + y_thisIsAnExtremelyLongVariableName;
};
std::cout << "x_thisIsAnExtremelyLongVariableName + y_thisIsAnExtremelyLongVariableName = " << addXY() << std::endl;
return 0;
}
這個限制就是當我們在捕獲變量時,只能使用相同的變數名稱去補獲。 (當變數名稱很奇怪時,會在你的 Lambda function 中出現) 當然這不是 c++ 14 要改善的主要原因。
C++14 引入了一項名為初始化捕獲(initializer capture)的功能,這使得在 lambda 表達式中捕獲變量變得更加靈活。它允許你在捕獲列表中進行變量的初始化,這對於需要在 lambda 表達式中使用臨時變量或計算值時特別有用。
使用時機
有主要以下 4 種:
計算複雜表達式
當你需要在 lambda 表達式中使用複雜的計算結果時,可以使用初始化捕獲來簡化代碼。
1
2
3
4
5
int a = 27;
int b = 37;
auto lambda = [sum = a * b + 3](int x) {
return sum + x;
};
捕獲臨時對象
當你需要在 lambda 表達式中使用臨時對象(如動態分配的內存、臨時字符串等)時,可以使用初始化捕獲來確保這些對象的生命週期覆蓋 lambda 表達式的使用範圍。
以下使用 std::move
,若不太熟悉的人,可以參考此篇
1
2
3
4
5
6
auto ptr = std::make_unique<int>(48);
auto lambda = [p = std::move(ptr)]() {
std::cout << *p << std::endl;
};
lambda();
重命名變量
如果你想在 lambda 表達式中使用不同的變量名稱,可以通過初始化捕獲來實現變量的重命名。
拿開頭的例子舉例
1
2
3
4
int x_thisIsAnExtremelyLongVariableName = 100;
auto lambda = [x = x_thisIsAnExtremelyLongVariableName](int y) {
return x + y;
};
捕獲參考
雖然通常可以通過 [&]
捕獲所有外部變量的引用,但有時你需要捕獲某些特定變量的引用,這時初始化捕獲也能派上用場。
1
2
3
4
5
6
int a = 45;
auto lambda = [&ref_a = a]() {
ref_a += 17;
};
lambda();
std::cout << "a: " << a << std::endl;
這些情境展示了初始化捕獲在不同場景中的應用,提供了更靈活和簡潔的編程方式。