前言
参考链接:
链接: C++ Lambda表达式详解
链接: 一文深入了解C++ lambda(C++17)
本篇使用的编译与运行命令为
g++ -std=gnu++2b test.cpp -o test.exe
./test.exe
标准lamda表达式:
[capture list] (parameter list) specifiers exception -> type { function body }
capture list是捕获列表,在应用中必填。
parameter list是参数列表,在应用中选填。
specifiers是限定符,在应用中选填。
exception是异常说明符,在应用中选填。
-> type是返回值类型,在应用中选填。
function body是表达式的函数体,在应用中必填。
探究lamda表达式的捕获列表
从下面2块代码的运行结果,可得出下面结论:
1.值捕获与引用捕获的使用区别
捕获列表 | 说明 |
---|---|
[] | 不使用捕获 |
[=] | 值捕获:捕获lamda表达式定义时的数据 |
[&] | 引用捕获:捕获使用lamda表达式时的数据 |
[this] | 捕获当前对象的指针,本质是引用捕获 |
[*this] | 捕获当前对象的副本,本质是值捕获 |
[=, &a] | 混合捕获:默认都使用值捕获,只有变量a使用引用捕获 |
[&, a] | 混合捕获:默认都使用引用捕获,只有变量a使用值捕获 |
2.lamda表达式出现嵌套时,主要关注当前的lamda表达式使用值捕获还是引用捕获
3.[this]和[*this]的区别
操作 | [this] | [*this] |
---|---|---|
调用类内的函数 | 可以 | 不可以 |
修改类内的变量 | 可以 | 不可以 |
查看this指针与获取类内的变量 | 可以 | 可以 |
this指针指向的地址 | 无变化 | 有变化 |
#include <iostream>
int main(int argc, char *argv[])
{
int a, b, c;
a = 10, b = 20, c = 30;
auto fun1 = [a, b]() -> int { // 变量a/b 以"值捕获"方式传入到表达式中
return a + b; // a == 10, b == 20
};
a = 110, b = 120, c = 130;
auto fun2 = [=]() -> int { // 将所有变量 以"值捕获"方式传入到表达式中
return fun1() + c; // fun1 == (10 + 20) = 30, c == 130
};
a = 210, b = 220, c = 230;
auto fun3 = [&a, fun1] -> int { // 变量a 以"引用捕获"方式传入到表达式中
a++; // a的值以调用时的值为准,即 a == 310,再进行 a++ 操作后,a == 411
return fun1();
};
a = 310, b = 320, c = 330;
auto fun4 = [&] -> int { // 将所有变量 以"引用捕获"方式传入到表达式中
a++; // a的值以调用时的值为准,即 a == 411,再进行 a++ 操作后,a == 412
b++; // b的值以调用时的值为准,即 b == 420,再进行 b++ 操作后,b == 421
return fun1() + c; // c的值以调用时的值为准,即 c == 430
};
a = 410, b = 420, c = 430;
auto fun5 = [=] -> int { // 将所有变量 以"值捕获"方式传入到表达式中
return fun4(); // fun4由于用"引用捕获",此时的a/b/c的值以fun5调用时为准,即 a == 412,b == 421,c == 430
};
int result1 = fun1(); // fun1内的变量a/b对应10/20,fun1 == 30
std::cout << "Running fun1: " << "a = " << a << ", b = " << b << ", c = " << c << std::endl;
std::cout << "result1: " << result1 << std::endl;
int result2 = fun2(); // fun2内的fun1/c对应30/130,fun2 == 160
std::cout << "Running fun2: " << "a = " << a << ", b = " << b << ", c = " << c << std::endl;
std::cout << "result2: " << result2 << std::endl;
int result3 = fun3(); // fun3内的fun1对应30,fun3 == 30
std::cout << "Running fun3: " << "a = " << a << ", b = " << b << ", c = " << c << std::endl;
std::cout << "result3: " << result3 << std::endl;
int result4 = fun4(); // fun4内的fun1/c对应30/430,fun4 == 460
std::cout << "Running fun4: " << "a = " << a << ", b = " << b << ", c = " << c << std::endl;
std::cout << "result4: " << result4 << std::endl;
int result5 = fun5(); // fun5内的fun4对应460,fun5 == 460
std::cout << "Running fun5: " << "a = " << a << ", b = " << b << ", c = " << c << std::endl;
std::cout << "result5: " << result5 << std::endl;
return 0;
}
运行结果:
Running fun1: a = 410, b = 420, c = 430
result1: 30
Running fun2: a = 410, b = 420, c = 430
result2: 160
Running fun3: a = 411, b = 420, c = 430
result3: 30
Running fun4: a = 412, b = 421, c = 430
result4: 460
Running fun5: a = 413, b = 422, c = 430
result5: 460
#include <iostream>
#include <functional>
class TestLamda {
public:
TestLamda() {}
~TestLamda() {}
void run();
void runTest1(std::string name) { std::cout << __func__ << ": " << name << std::endl; }
void runTest2(std::string name) { std::cout << __func__ << ": " << name << std::endl; }
private:
int m_runCnt;
};
void TestLamda::run()
{
typedef std::function<void(void)> TestFunc;
m_runCnt = 10;
TestFunc testFunc1 = [this](void) {
this->runTest1("1");
this->m_runCnt += 1;
std::cout << "testFunc1 " << this << ": " << this->m_runCnt << std::endl;
};
TestFunc testFunc2 = [*this](void) {
// *this->runTest2("1");
// this->m_runCnt = 0;
std::cout << "testFunc2 " << this << ": " << this->m_runCnt << std::endl;
};
m_runCnt = 1000;
std::cout << "run " << this << ": " << this->m_runCnt << std::endl;
testFunc1();
std::cout << "run " << this << ": " << this->m_runCnt << std::endl;
testFunc2();
std::cout << "run " << this << ": " << this->m_runCnt << std::endl;
}
int main(int argc, char *argv[])
{
TestLamda testInstance;
testInstance.run();
return 0;
}
运行结果:
run 0xeed5ff8ec: 1000
runTest1: 1
testFunc1 0xeed5ff8ec: 1001
run 0xeed5ff8ec: 1001
testFunc2 0x13b20581730: 10
run 0xeed5ff8ec: 1001