C++中的Lambda表达式

发布于:2024-11-27 ⋅ 阅读:(111) ⋅ 点赞:(0)

定义:

在C++中,lambda表达式(也叫匿名函数)是一种可以在代码中定义匿名函数对象的便捷方式。

lambda表达式的基本形式是:

 capture list -> return_type { function body } 。

1)[capture list] 是捕获列表,用于指定lambda表达式所在作用域中的变量如何被捕获(可以是值传递或者引用传递),例如 [&] 表示以引用方式捕获所有外部变量, [=] 表示以值的方式捕获所有外部变量。

2)(parameters) 是参数列表,和普通函数的参数列表类似,用于传递参数给lambda函数。如果没有参数,可以写为空括号 () 。

3)-> return_type 是返回值类型部分,用于指定lambda表达式返回值的类型。如果可以自动推断返回类型,这部分可以省略。

4){ function body } 是函数体,包含了lambda表达式要执行的语句。

例如,有一个 vector 存放整数,我们可以使用lambda表达式来进行排序:

#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> numbers = {5, 2, 8, 1, 9};
std::sort(numbers.begin(), numbers.end(), [](int a, int b) {
return a < b;
});
for (int num : numbers) {
std::cout << num << " ";
}
return 0;
}

在这个例子中, [](int a, int b) { return a < b; } 就是一个lambda表达式,作为 std::sort 函数的比较函数,用来指定排序规则。

作用:

1.作为回调函数

许多C++标准库算法需要回调函数来指定操作。比如 std::for_each ,它会对序列中的每个元素执行一个操作,这个操作就可以用lambda表达式来定义。

#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
std::for_each(v.begin(), v.end(), [](int i) {
std::cout << i * 2 << " ";
});
return 0;
}

在这个例子中, lambda 表达式 [](int i) { std::cout

2.用于排序和比较操作

在使用 std::sort 等函数时,可以用lambda表达式定义比较规则。

#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> numbers = {4, 2, 7, 1, 9};
std::sort(numbers.begin(), numbers.end(), [](int a, int b) {
return a > b;
});
for (int num : numbers) {
std::cout << num << " ";
}
return 0;
}

这里的lambda表达式 [](int a, int b) { return a > b; } 定义了从大到小的排序规则。

3)事件处理

在一些简单的事件驱动编程场景中,lambda表达式可以作为事件处理器。虽然C++不是主要用于事件驱动编程的语言,但在简单的图形界面库或者简单的异步编程场景下可以使用。

#include <iostream>
#include <functional>
class Button {
public:
std::function<void()> onClick;
};
int main() {
Button button;
button.onClick =  {
std::cout << "Button Clicked!" << " ";
};
button.onClick();
return 0;
}

这个例子简单模拟了一个按钮点击事件, lambda 表达式  { std::cout

捕获变量的类型:

1.局部自动变量(栈变量)

这是最常见的情况。例如在一个函数内部定义的普通变量。

#include <iostream>
int main() {
int num = 10;
// 捕获局部自动变量num
auto lambda = num {
std::cout << num << std::endl;
};
lambda();
return 0;
}

在这个例子中,lambda表达式捕获了函数 main 中的局部变量 num 。

2.静态局部变量

可以捕获在函数内定义的静态变量。

#include <iostream>
int main() {
static int static_num = 20;
auto lambda = static_num {
std::cout << static_num << std::endl;
};
lambda();
return 0;
}

这里lambda表达式捕获了静态局部变量 static_num 。

3.类成员变量(在类的成员函数中)

当lambda表达式在类的成员函数中定义时,可以捕获类的成员变量。不过要注意捕获方式和成员访问权限等问题。

#include <iostream>
class MyClass {
public:
int member_var = 30;
void func() {
// 捕获类成员变量member_var
auto lambda = this {
std::cout << this->member_var << std::endl;
};
lambda();
}
};
int main() {
MyClass obj;
obj.func();
return 0;
}

在这个类的成员函数 func 中,lambda表达式通过 [this] 捕获了类 MyClass 的成员变量 member_var 。

捕获方式:

1.按值捕获([=])

会捕获lambda表达式所在作用域的所有变量,并且以副本的形式使用这些变量。

#include <iostream>
int main() {
int num = 10;
auto lambda = = {
std::cout << num << std::endl;
};
lambda();
num = 20;
lambda();
return 0;
}

在这个例子中,lambda表达式按值捕获了 num 变量。即使在调用lambda表达式后修改 num 的值,lambda表达式内部使用的 num 值依旧是捕获时的值(10)。

2.按引用捕获([&])

捕获lambda表达式所在作用域的所有变量的引用,对捕获变量的修改会影响外部变量。

#include <iostream>
int main() {
int num = 10;
auto lambda = & {
std::cout << num << std::endl;
num = 20;
};
lambda();
std::cout << num << std::endl;
return 0;
}

这里lambda表达式按引用捕获 num ,在lambda表达式内部修改 num 的值,外部的 num 变量也会随之改变。

3.混合捕获([=, &var]或者[&, =var])

可以指定部分变量按值捕获,部分变量按引用捕获。例如 [=, &num] 表示除了 num 按引用捕获外,其他变量按值捕获。

#include <iostream>
int main() {
int num1 = 10;
int num2 = 20;
auto lambda = =, &num1 {
std::cout << num1 << " " << num2 << std::endl;
num1 = 30;
};
lambda();
std::cout << num1 << std::endl;
return 0;
}

在这个lambda表达式中, num1 按引用捕获, num2 按值捕获。修改 num1 的值会影响外部变量 num1 的值。

4.捕获特定变量([var])

只捕获指定的变量,并且以副本形式捕获。

#include <iostream>
int main() {
int a = 5, b = 10;
auto lambda = a {
std::cout << a << std::endl;
};
lambda();
return 0;
}

此lambda表达式仅捕获 a 变量, b 变量未被捕获,在lambda表达式内部无法访问 b 。


网站公告

今日签到

点亮在社区的每一天
去签到