我假设您对 C# 中的 lambdas 有经验,那么我们在这里要做的就是介绍 C++ 采用的语法。所有代码片段都来自同一个示例中的同一个文件。
示例:λsample \λsample . CPP
// Create a lambda-expression closure.
auto lm1 = []()
{
wcout << L"No capture, parameterless lambda." << endl;
};
// Invoke the lambda.
lm1();
// Create a lambda closure with parameters.
auto lm2 = [](int a, int b)
{
wcout << a << L" + " << b << " = " << (a + b) << endl;
};
lm2(3,4);
这里的尾随返回类型是参数规范后的-> int
。
// Create a lambda closure with a trailing return type.
auto lm3 = [](int a, int b) -> int
{
wcout << a << L" % " << b << " = ";
return a % b;
};
wcout << lm3(7, 5) << endl;
int a = 5;
int b = 6;
// Capture by copy all variables that are currently in the scope.
// Note also that we do not need to capture the closure;
// here we simply invoke the anonymous lambda with the
// () after the closing brace.
[=]()
{
wcout << a << L" + " << b << " = " << (a + b) << endl;
//// It's illegal to modify a here because we have
//// captured by value and have not specified that
//// this lambda should be treated as mutable.
//a = 10;
}();
[=]() mutable -> void
{
wcout << a << L" + " << b << " = " << (a + b) << endl;
// By marking this lambda as mutable, we can now modify a.
// Since we are capturing by value, the modifications
// will not propagate outside.
a = 10;
}();
wcout << L"The value of a is " << a << L"." << endl;
[&]()
{
wcout << a << L" + " << b << " = " << (a + b) << endl;
// By capturing by reference, we now do not need
// to mark this as mutable.
// Because it is a reference, though, changes now
// propagate out.
a = 10;
}();
wcout << L"The value of a is " << a << L"." << endl;
// Here we specify explicitly that we are capturing a by
// value and b as a reference.
[a,&b]()
{
b = 12;
wcout << a << L" + " << b << " = " << (a + b) << endl;
}();
// Here we specify explicitly that we are capturing b as
// a reference and that all other captures should be by
// value.
[=,&b]()
{
b = 15;
wcout << a << L" + " << b << " = " << (a + b) << endl;
}();
// Here we specify explicitly that we are capturing a by
// value and that all other captures should be by reference.
[&,a]()
{
b = 18;
wcout << a << L" + " << b << " = " << (a + b) << endl;
}();
在类成员函数中使用 lambda 时,不能通过引用使用默认捕获。这是因为 lambda 会有一个this
指针,必须复制。此外,在处理引用计数的智能指针时,经常会遇到 lambda 持有对类的引用的问题。通常情况下,您永远不会回到引用计数为零,从而导致程序内存泄漏。