lambda表达式也称为匿名函数,其基本语法结构如下:
xxxxxxxxxx
41[capture](params) opt -> retureType
2{
3body;
4}
其中capture是捕获列表,params是参数列表,opt是函数选项,retureType是返回值类型,body是函数体。
在lambda表达式中:
[] 捕获列表:捕获lambda表达式函数体外的局部变量;
() 函数的参数列表
{} 函数的函数体
如果没有在[]中捕获局部变量,那么在匿名函数的函数体中无法访问它们。进一步的,还可以给匿名函数增加函数参数,以及指定函数返回类型。
Note
捕获列表捕获的是局部变量,全局变量不需要捕获。
如果想要通过捕获列表改变局部变量的值,函数选项的位置加上mutable关键字才能对局部变量进行修改操作,但这样做也并不能修改局部变量实际的值。
联想到常规函数的值传递场景,想要真正通过形参改变实参,形参需要写成引用形式。
那么对于匿名函数而言,如果想要在匿名函数中修改捕获的变量其本身的值,那么应该采用的是引用捕获。
(1)lambda表达式的参数列表与普通函数的参数列表一样,如果没有参数,则参数列表可以省略不写;
(2)如果没有需要捕获的内容,需要写上[];
(3)选项如非必需,可以省略:
mutable: 可以修改按值传递进来的拷贝(注意是能修改拷贝,而不是值本身)
noexcept:
noexcept
是一种约定,向编译器和调用者保证函数不会抛出异常。如果违反了这个约定,程序的行为将是未定义的,通常会导致程序终止。(4)返回类型可以省略。一般情况下,不指定lambda表达式的返回值,编译器会根据return语句自动推导返回值的类型,但需要注意的是labmda表达式不能通过列表初始化自动推导出返回值类型。
lambda表达式本身的返回值是一个函数对象(function object),也称为闭包对象(closure object)。这个对象的类型是编译器生成的唯一匿名类型。
每个lambda表达式都有唯一的匿名类型:
xxxxxxxxxx
171
2
3
4int main() {
5 auto lambda1 = [](int x) { return x + 1; };
6 auto lambda2 = [](int x) { return x + 1; }; // 相同代码,但类型不同
7
8 // 两个lambda有不同的类型
9 std::cout << std::boolalpha;
10 std::cout << "Same type? " << std::is_same_v<decltype(lambda1), decltype(lambda2)> << std::endl; // false
11
12 // 但都可以转换为函数指针(无捕获时)
13 int (*ptr1)(int) = lambda1;
14 int (*ptr2)(int) = lambda2;
15
16 return 0;
17}
lambda表达式实际上是编译器生成的类的语法糖:
xxxxxxxxxx
221// 这个lambda表达式:
2auto lambda = [x, &y](int a) mutable -> int {
3 x += a;
4 y += a;
5 return x + y;
6};
7
8// 大致等价于编译器生成的类:
9class CompilerGeneratedLambda {
10private:
11 int x; // 按值捕获
12 int& y; // 按引用捕获
13
14public:
15 CompilerGeneratedLambda(int x_val, int& y_ref) : x(x_val), y(y_ref) {}
16
17 int operator()(int a) { // mutable允许修改按值捕获的变量
18 x += a;
19 y += a;
20 return x + y;
21 }
22};
无捕获Lambda
xxxxxxxxxx
141
2
3int main() {
4 // 无捕获的lambda可以转换为函数指针
5 auto lambda = [](int x, int y) { return x + y; };
6
7 // 可以转换为函数指针
8 int (*func_ptr)(int, int) = lambda;
9
10 std::cout << lambda(3, 4) << std::endl; // 7
11 std::cout << func_ptr(3, 4) << std::endl; // 7
12
13 return 0;
14}
有捕获Lambda
xxxxxxxxxx
191
2
3int main() {
4 int multiplier = 10;
5
6 // 有捕获的lambda不能直接转换为函数指针
7 auto lambda = [multiplier](int x) { return x * multiplier; };
8
9 // 这行会编译错误:
10 // int (*func_ptr)(int) = lambda; // Error!
11
12 // 但可以使用std::function
13 std::function<int(int)> func = lambda;
14
15 std::cout << lambda(5) << std::endl; // 50
16 std::cout << func(5) << std::endl; // 50
17
18 return 0;
19}
xxxxxxxxxx
281
2
3
4
5
6int main() {
7 std::vector<int> numbers = {1, 2, 3, 4, 5};
8 int factor = 3;
9
10 // 1. 直接使用auto存储
11 auto multiplier = [factor](int x) { return x * factor; };
12
13 // 2. 使用std::function存储(类型擦除)
14 std::function<int(int)> func_multiplier = [factor](int x) { return x * factor; };
15
16 // 3. 作为模板参数传递(保持类型)
17 std::transform(numbers.begin(), numbers.end(), numbers.begin(), multiplier);
18
19 // 4. 返回lambda的函数
20 auto create_multiplier = [](int factor) {
21 return [factor](int x) { return x * factor; }; // 返回lambda对象
22 };
23
24 auto times_two = create_multiplier(2);
25 std::cout << times_two(10) << std::endl; // 20
26
27 return 0;
28}
xxxxxxxxxx
191
2
3int main() {
4 // 无捕获lambda的大小
5 auto no_capture = [](int x) { return x * 2; };
6 std::cout << "No capture size: " << sizeof(no_capture) << std::endl; // 通常是1
7
8 int a = 10, b = 20;
9
10 // 有捕获lambda的大小
11 auto with_capture = [a, b](int x) { return x + a + b; };
12 std::cout << "With capture size: " << sizeof(with_capture) << std::endl; // 通常是8(两个int)
13
14 // 引用捕获的大小
15 auto ref_capture = [&a, &b](int x) { return x + a + b; };
16 std::cout << "Ref capture size: " << sizeof(ref_capture) << std::endl; // 通常是16(两个指针)
17
18 return 0;
19}
Lambda表达式本身的返回值是:
函数对象:具有唯一匿名类型的可调用对象
闭包对象:包含捕获变量的状态
编译器生成的类实例:重载了operator()
的对象
可转换性:
无捕获lambda → 函数指针
有捕获lambda → 只能用std::function
或模板
关键特点:
每个lambda表达式都有唯一类型
大小取决于捕获的变量
生命周期独立于定义位置(按值捕获)
支持泛型编程(C++14+)
Lambda表达式返回的不是函数执行的结果,而是一个可以被调用的函数对象本身。
STL(Standard Template Library)提供了丰富的算法库,这些算法定义在<algorithm>
头文件中。以下是按功能分类的常用算法:
std::for_each
是 STL 中最常用的算法之一,用于对容器中的每个元素执行指定的操作。
xxxxxxxxxx
41
2
3template<typename InputIt, typename UnaryFunction>
4UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f);
参数说明:
first
, last
:迭代器范围 [first, last)
f
:一元函数对象,接受容器元素作为参数
返回值:返回传入的函数对象 f
1. 使用普通函数
xxxxxxxxxx
161
2
3
4
5void print_element(int x) {
6 std::cout << x << " ";
7}
8
9int main() {
10 std::vector<int> vec = {1, 2, 3, 4, 5};
11
12 std::for_each(vec.begin(), vec.end(), print_element);
13 // 输出: 1 2 3 4 5
14
15 return 0;
16}
2. 使用 Lambda 表达式
xxxxxxxxxx
271
2
3
4
5int main() {
6 std::vector<int> vec = {1, 2, 3, 4, 5};
7
8 // 打印每个元素
9 std::for_each(vec.begin(), vec.end(), [](int x) {
10 std::cout << x << " ";
11 });
12
13 std::cout << std::endl;
14
15 // 修改每个元素(需要引用)
16 std::for_each(vec.begin(), vec.end(), [](int& x) {
17 x *= 2;
18 });
19
20 // 再次打印
21 std::for_each(vec.begin(), vec.end(), [](int x) {
22 std::cout << x << " ";
23 });
24 // 输出: 2 4 6 8 10
25
26 return 0;
27}
3. 使用函数对象(Functor)
xxxxxxxxxx
281
2
3
4
5class Multiplier {
6private:
7 int factor;
8public:
9 Multiplier(int f) : factor(f) {}
10
11 void operator()(int& x) {
12 x *= factor;
13 }
14};
15
16int main() {
17 std::vector<int> vec = {1, 2, 3, 4, 5};
18
19 // 使用函数对象将每个元素乘以3
20 std::for_each(vec.begin(), vec.end(), Multiplier(3));
21
22 std::for_each(vec.begin(), vec.end(), [](int x) {
23 std::cout << x << " ";
24 });
25 // 输出: 3 6 9 12 15
26
27 return 0;
28}
4. 返回值的使用
std::for_each
返回传入的函数对象,这在某些情况下很有用:
xxxxxxxxxx
231
2
3
4
5class Counter {
6public:
7 int count = 0;
8
9 void operator()(int x) {
10 count++;
11 std::cout << x << " ";
12 }
13};
14
15int main() {
16 std::vector<int> vec = {1, 2, 3, 4, 5};
17
18 Counter counter = std::for_each(vec.begin(), vec.end(), Counter());
19
20 std::cout << "\nProcessed " << counter.count << " elements" << std::endl;
21
22 return 0;
23}
xxxxxxxxxx
241
2
3
4
5int main() {
6 std::vector<int> vec = {1, 2, 3, 4, 5, 3, 6};
7
8 // find - 查找第一个匹配元素
9 auto it = std::find(vec.begin(), vec.end(), 3);
10 if (it != vec.end()) {
11 std::cout << "Found 3 at position: " << std::distance(vec.begin(), it) << std::endl;
12 }
13
14 // find_if - 根据条件查找
15 auto it2 = std::find_if(vec.begin(), vec.end(), [](int x) { return x > 4; });
16 if (it2 != vec.end()) {
17 std::cout << "First element > 4: " << *it2 << std::endl;
18 }
19
20 // find_if_not - 查找不满足条件的元素
21 auto it3 = std::find_if_not(vec.begin(), vec.end(), [](int x) { return x < 4; });
22
23 return 0;
24}
xxxxxxxxxx
191
2
3
4int main() {
5 std::vector<int> vec = {1, 2, 3, 4, 5, 6, 7};
6 std::vector<int> pattern = {3, 4, 5};
7
8 // search - 查找子序列
9 auto it = std::search(vec.begin(), vec.end(), pattern.begin(), pattern.end());
10 if (it != vec.end()) {
11 std::cout << "Pattern found at position: " << std::distance(vec.begin(), it) << std::endl;
12 }
13
14 // binary_search - 二分查找(需要有序)
15 std::vector<int> sorted_vec = {1, 2, 3, 4, 5, 6, 7};
16 bool found = std::binary_search(sorted_vec.begin(), sorted_vec.end(), 4);
17
18 return 0;
19}
xxxxxxxxxx
251
2
3
4
5int main() {
6 std::vector<int> vec = {5, 2, 8, 1, 9, 3};
7
8 // sort - 排序
9 std::sort(vec.begin(), vec.end());
10 // 降序排序
11 std::sort(vec.begin(), vec.end(), std::greater<int>());
12
13 // partial_sort - 部分排序(只排序前n个元素)
14 std::vector<int> vec2 = {5, 2, 8, 1, 9, 3};
15 std::partial_sort(vec2.begin(), vec2.begin() + 3, vec2.end());
16
17 // nth_element - 找到第n大的元素
18 std::vector<int> vec3 = {5, 2, 8, 1, 9, 3};
19 std::nth_element(vec3.begin(), vec3.begin() + 2, vec3.end());
20
21 // stable_sort - 稳定排序
22 std::stable_sort(vec.begin(), vec.end());
23
24 return 0;
25}
xxxxxxxxxx
231
2
3
4
5int main() {
6 std::vector<int> source = {1, 2, 3, 4, 5};
7 std::vector<int> dest(5);
8
9 // copy - 复制
10 std::copy(source.begin(), source.end(), dest.begin());
11
12 // copy_if - 条件复制
13 std::vector<int> even_numbers;
14 std::copy_if(source.begin(), source.end(),
15 std::back_inserter(even_numbers),
16 [](int x) { return x % 2 == 0; });
17
18 // copy_n - 复制n个元素
19 std::vector<int> first_three(3);
20 std::copy_n(source.begin(), 3, first_three.begin());
21
22 return 0;
23}
xxxxxxxxxx
181
2
3
4int main() {
5 std::vector<int> vec = {1, 2, 3, 4, 5};
6 std::vector<int> result(vec.size());
7
8 // transform - 变换每个元素
9 std::transform(vec.begin(), vec.end(), result.begin(),
10 [](int x) { return x * x; });
11
12 // transform - 两个序列的变换
13 std::vector<int> vec2 = {1, 1, 1, 1, 1};
14 std::transform(vec.begin(), vec.end(), vec2.begin(), result.begin(),
15 [](int a, int b) { return a + b; });
16
17 return 0;
18}
xxxxxxxxxx
221
2
3
4
5int main() {
6 std::vector<int> vec(10);
7
8 // fill - 填充固定值
9 std::fill(vec.begin(), vec.end(), 42);
10
11 // fill_n - 填充n个元素
12 std::fill_n(vec.begin(), 5, 100);
13
14 // generate - 用函数生成值
15 std::random_device rd;
16 std::mt19937 gen(rd());
17 std::uniform_int_distribution<> dis(1, 100);
18
19 std::generate(vec.begin(), vec.end(), [&]() { return dis(gen); });
20
21 return 0;
22}
xxxxxxxxxx
231
2
3
4int main() {
5 std::vector<int> vec = {1, 2, 3, 2, 4, 2, 5};
6
7 // remove - 移除特定值(不改变容器大小)
8 auto new_end = std::remove(vec.begin(), vec.end(), 2);
9 vec.erase(new_end, vec.end()); // 真正删除
10
11 // remove_if - 条件移除
12 std::vector<int> vec2 = {1, 2, 3, 4, 5, 6, 7, 8};
13 auto new_end2 = std::remove_if(vec2.begin(), vec2.end(),
14 [](int x) { return x % 2 == 0; });
15 vec2.erase(new_end2, vec2.end());
16
17 // unique - 移除连续重复元素
18 std::vector<int> vec3 = {1, 1, 2, 2, 2, 3, 3, 4};
19 auto new_end3 = std::unique(vec3.begin(), vec3.end());
20 vec3.erase(new_end3, vec3.end());
21
22 return 0;
23}
xxxxxxxxxx
291
2
3
4
5int main() {
6 std::vector<int> vec = {1, 2, 3, 4, 5};
7
8 // accumulate - 累积
9 int sum = std::accumulate(vec.begin(), vec.end(), 0);
10 int product = std::accumulate(vec.begin(), vec.end(), 1, std::multiplies<int>());
11
12 // partial_sum - 部分和
13 std::vector<int> partial_sums(vec.size());
14 std::partial_sum(vec.begin(), vec.end(), partial_sums.begin());
15
16 // adjacent_difference - 相邻差值
17 std::vector<int> differences(vec.size());
18 std::adjacent_difference(vec.begin(), vec.end(), differences.begin());
19
20 // inner_product - 内积
21 std::vector<int> vec2 = {2, 3, 4, 5, 6};
22 int dot_product = std::inner_product(vec.begin(), vec.end(), vec2.begin(), 0);
23
24 // iota - 递增序列
25 std::vector<int> sequence(10);
26 std::iota(sequence.begin(), sequence.end(), 1); // 1, 2, 3, ..., 10
27
28 return 0;
29}
xxxxxxxxxx
331
2
3
4
5int main() {
6 std::vector<int> set1 = {1, 2, 3, 4, 5};
7 std::vector<int> set2 = {3, 4, 5, 6, 7};
8 std::vector<int> result;
9
10 // set_union - 并集
11 std::set_union(set1.begin(), set1.end(),
12 set2.begin(), set2.end(),
13 std::back_inserter(result));
14
15 // set_intersection - 交集
16 result.clear();
17 std::set_intersection(set1.begin(), set1.end(),
18 set2.begin(), set2.end(),
19 std::back_inserter(result));
20
21 // set_difference - 差集
22 result.clear();
23 std::set_difference(set1.begin(), set1.end(),
24 set2.begin(), set2.end(),
25 std::back_inserter(result));
26
27 // includes - 检查是否包含
28 std::vector<int> subset = {2, 3, 4};
29 bool is_subset = std::includes(set1.begin(), set1.end(),
30 subset.begin(), subset.end());
31
32 return 0;
33}
xxxxxxxxxx
251
2
3
4int main() {
5 std::vector<int> vec = {3, 1, 4, 1, 5, 9, 2, 6};
6
7 // make_heap - 建堆
8 std::make_heap(vec.begin(), vec.end());
9
10 // push_heap - 添加元素到堆
11 vec.push_back(8);
12 std::push_heap(vec.begin(), vec.end());
13
14 // pop_heap - 从堆中移除最大元素
15 std::pop_heap(vec.begin(), vec.end());
16 vec.pop_back();
17
18 // sort_heap - 堆排序
19 std::sort_heap(vec.begin(), vec.end());
20
21 // is_heap - 检查是否为堆
22 bool is_heap = std::is_heap(vec.begin(), vec.end());
23
24 return 0;
25}
xxxxxxxxxx
261
2
3
4
5int main() {
6 std::vector<int> vec = {1, 2, 3};
7
8 // next_permutation - 下一个排列
9 do {
10 for (int x : vec) {
11 std::cout << x << " ";
12 }
13 std::cout << std::endl;
14 } while (std::next_permutation(vec.begin(), vec.end()));
15
16 // prev_permutation - 上一个排列
17 std::vector<int> vec2 = {3, 2, 1};
18 do {
19 for (int x : vec2) {
20 std::cout << x << " ";
21 }
22 std::cout << std::endl;
23 } while (std::prev_permutation(vec2.begin(), vec2.end()));
24
25 return 0;
26}
xxxxxxxxxx
211
2
3
4int main() {
5 std::vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
6
7 // partition - 分区
8 auto pivot = std::partition(vec.begin(), vec.end(),
9 [](int x) { return x % 2 == 0; });
10
11 // stable_partition - 稳定分区
12 std::vector<int> vec2 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
13 auto pivot2 = std::stable_partition(vec2.begin(), vec2.end(),
14 [](int x) { return x % 2 == 0; });
15
16 // is_partitioned - 检查是否已分区
17 bool partitioned = std::is_partitioned(vec.begin(), vec.end(),
18 [](int x) { return x % 2 == 0; });
19
20 return 0;
21}
xxxxxxxxxx
241
2
3
4int main() {
5 std::vector<int> vec = {3, 1, 4, 1, 5, 9, 2, 6};
6
7 // min_element / max_element
8 auto min_it = std::min_element(vec.begin(), vec.end());
9 auto max_it = std::max_element(vec.begin(), vec.end());
10
11 // minmax_element - 同时找最小和最大
12 auto minmax = std::minmax_element(vec.begin(), vec.end());
13
14 // min / max - 比较两个值
15 int a = 5, b = 3;
16 int smaller = std::min(a, b);
17 int larger = std::max(a, b);
18
19 // clamp - 限制在范围内(C++17)
20 int value = 15;
21 int clamped = std::clamp(value, 1, 10); // 结果为10
22
23 return 0;
24}
xxxxxxxxxx
191
2
3
4int main() {
5 std::vector<int> vec1 = {1, 2, 3, 4, 5};
6 std::vector<int> vec2 = {1, 2, 3, 4, 6};
7
8 // equal - 检查是否相等
9 bool are_equal = std::equal(vec1.begin(), vec1.end(), vec2.begin());
10
11 // lexicographical_compare - 字典序比较
12 bool less_than = std::lexicographical_compare(vec1.begin(), vec1.end(),
13 vec2.begin(), vec2.end());
14
15 // mismatch - 找到第一个不匹配的位置
16 auto mismatch_pair = std::mismatch(vec1.begin(), vec1.end(), vec2.begin());
17
18 return 0;
19}