构造一个闭包:一个匿名函数对象可以捕获作用域内的变量。其完整形式为:
[ captures ] (optional)(c++20) ( params ) specifiers exception attr -> ret requires(optional)(c++20) { body }
// 可以使用如下类来替代lambda表达式
class Module_print {
private:
std::ostream& os;
int m;
public:
// 注意引用必须使用成员列表初始化
Module_print(std::ostream &s, int mm) : os(s), m(mm) { }
// 注意默认情况下lambda无法修改捕获到的变量,故这里加const使其无法修改成员变量
void operator()(int x) const
{
if (x % m == 0) {
os << x << '\n';
}
}
};
// 使用for_each需要包含头文件#include
void print_module_v0(const std::vector& v, std::ostream& os, int m)
{
for_each(begin(v), end(v), [&os, m](int x) {if (x % m == 0) os << x << '\n'; });
}
void print_module_v1(const std::vector& v, std::ostream& os, int m)
{
for_each(begin(v), end(v), Module_print{os, m});
}
void lam_cap(void)
{
char c = 'X';
int num = 6;
double point = 9.8765;
std::string str{"hello lambda"};
// 空捕获列表无法捕获任何局部变量,但可以访问全局对象cout和endl.
auto lam0 = [](void) { std::cout << "null" << std::endl; };
lam0();
// 引用隐式捕获,所有局部变量都能通过引用访问
auto lam1 = [&](void) {
std::cout << "lam1: The char c is " << c << ","
<< "The num is " << num << ","
<< "The point is " << point << ","
<< "The str is: " << str << std::endl; };
lam1();
// 值隐式捕获,所有局部变量都能通过值即副本访问
auto lam2 = [=](void) {
std::cout << "lam2: The char c is " << c << ","
<< "The num is " << num << ","
<< "The point is " << point << ","
<< "The str is: " << str << std::endl; };
lam2();
// 通过引用捕获指定的局部变量num和c
auto lam3 = [&num, &c](void) {
std::cout << "lam3: The char c is " << c << ","
<< "The num is " << num << std::endl; };
lam3();
// 通过值捕获指定的局部变量point和str
auto lam4 = [point, str](void) {
std::cout << "lam4: The point is " << point << ","
<< "The str is: " << str << std::endl; };
lam4();
// 除了局部变量c其他的局部变量均通过引用隐式捕获,这里c通过值捕获,注意列出的变量不能再以&开头了
auto lam5 = [&, c](void) {
std::cout << "lam5: The char c is " << c << ","
<< "The num is " << num << ","
<< "The point is " << point << ","
<< "The str is: " << str << std::endl; }; // 除了‘c’其他的都通过引用访问
lam5();
// 除了局部变量str靠引用捕获外其他的局部变量均通过值来捕获
auto lam6 = [=, &str](void) {
std::cout << "lam6: The char c is " << c << ","
<< "The num is " << num << ","
<< "The point is " << point << ","
<< "The str is: " << str << std::endl; }; // 除了str其他的都通过值传递
lam6();
// 通过“->”来显式指明其返回类型
auto lam7 = [&]()->char {return c; };
std::cout << "lam7 return is " << lam7() << std::endl;
// 如果一个lambda什么也不捕获则可以将其赋给一个函数指针,否则只能使用auto
int(*lam8)(int) = [](int a) {return a * a; };
std::cout << "lam8 return is " << lam8(4) << std::endl;
}
class Test {
private:
char m_var0;
int m_var1;
double m_var2;
public:
Test(const char arg1, const int arg2, const double arg3) : m_var0(arg1), m_var1(arg2), m_var2(arg3) { }
void print_m(void)
{
// 可以通过this指针访问成员变量
// auto L1 = [this]() { std::cout << "m_var0 is " << m_var0 << ',' << " m_var1 is " << m_var1 << ',' << " m_var2 is " << m_var2 << std::endl; };
// 这样无法访问其成员变量
// auto L1 = []() { std::cout << "m_var0 is " << m_var0 << ',' << " m_var1 is " << m_var1 << ',' << " m_var2 is " << m_var2 << std::endl; };
// 加mutable可以修改捕获到的成员变量
auto L1 = [this]() mutable { std::cout << "m_var0 is " << ++m_var0 << ',' << " m_var1 is " << ++m_var1 << ',' << " m_var2 is " << ++m_var2 << std::endl; };
L1();
}
};