V Lambda 表达式.cpp
本文介绍了C++中Lambda表达式的基本概念、捕获机制和应用场景。Lambda表达式是一种匿名函数,通过捕获列表([=]、[&]或显式指定)访问外部变量。文章展示了Lambda在算法排序、多线程任务和回调函数中的典型用法,并介绍了带参数、递归调用和访问成员函数等进阶技巧。Lambda表达式能简化代码结构,提升可读性和可维护性,是C++中强大的函数式编程工具。
前言: Lambda 表达式是一种强大而灵活的工具,它允许我们直接在代码中定义匿名函数对象。
一、初识 Lambda 表达式
Lambda 表达式是一种匿名函数,它没有名字,但具有函数的特性。它的基本语法结构如下:
capture list->return type {body}
-
捕获列表(Capture list):规定 Lambda 表达式可以访问哪些外部变量。
-
参数列表(Parameters):与普通函数的参数列表相同。
-
返回类型(Return type):可选部分,默认由编译器推断。
-
函数体(Body):包含函数的具体实现代码。
最简单的 Lambda 表达式示例:
#include <iostream>
int main() {
auto lambda = []() { std::cout << "Lambda 表达式:你好,世界!" << std::endl; };
lambda(); // 调用 Lambda 表达式
return 0;
}
在这个例子中,我们定义了一个没有参数、没有返回值的 Lambda 表达式,auto
关键字用于自动推断其类型。运行程序会输出:“Lambda 表达式:你好,世界!”
二、捕获机制详解
Lambda 表达式可以通过捕获列表访问其定义所在作用域中的变量。
1. 按值捕获(Copy Capture):[=]
#include <iostream>
int main() {
int x = 10;
int y = 20;
auto lambda = [=]() { std::cout << "按值捕获:x = " << x << ", y = " << y << std::endl; };
lambda();
return 0;
}
在这个例子中,Lambda 表达式捕获了 x
和 y
的值。这意味着即使在 Lambda 表达式定义之后修改 x
和 y
,Lambda 表达式内部的值也不会改变。程序输出:“按值捕获:x = 10, y = 20”
2. 按引用捕获(Reference Capture):[&]
#include <iostream>
int main() {
int x = 10;
int y = 20;
auto lambda = [&](int a) { x = a; std::cout << "按引用捕获:x = " << x << ", y = " << y << std::endl; };
lambda(30);
std::cout << "主函数中 x 的值: " << x << std::endl; // 输出修改后的 x 值
return 0;
}
在这个例子中,Lambda 表达式捕获了 x
和 y
的引用。修改 Lambda 表达式中的 x
值会直接影响到原始变量 x
。程序输出:
按引用捕获:x = 30, y = 20
主函数中 x 的值: 30
3. 显式捕获
可以显式指定捕获哪些变量以及捕获方式:
#include <iostream>
int main() {
int x = 10;
int y = 20;
auto lambda = [x, &y]() { std::cout << "显式捕获:x = " << x << ", y = " << y << std::endl; };
lambda();
return 0;
}
这里,x
按值捕获,y
按引用捕获。程序输出:“显式捕获:x = 10, y = 20”
三、Lambda 表达式的应用场景
1. 算法库中的使用
C++ 标准库中的算法库(如 sort
、for_each
等)常需要函数对象作为参数,Lambda 表达式可以方便地定义这些函数对象。
-
自定义排序规则
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {5, 2, 8, 1, 3};
std::sort(vec.begin(), vec.end(), [](int a, int b) { return a > b; }); // 按降序排序
for (int x : vec) {
std::cout << x << " ";
}
std::cout << std::endl;
return 0;
}
程序输出:
8 5 3 2 1
2. 多线程编程中的使用
在多线程编程中,Lambda 表达式可以用于定义线程的任务函数,捕获当前作用域中的变量并在线程中使用。
#include <iostream>
#include <thread>
int main() {
int x = 5;
std::thread t([x] {
std::cout << "线程中捕获的值:x = " << x << std::endl;
});
t.join();
return 0;
}
程序输出:
线程中捕获的值:x = 5
3. 回调函数的使用
在需要传递回调函数的场景下,Lambda 表达式可以提供简洁的解决方案。
#include <iostream>
#include <vector>
#include <functional>
class EventHandler {
public:
void addCallback(std::function<void()> callback) {
callbacks.push_back(callback);
}
void trigger() {
for (auto& callback : callbacks) {
callback();
}
}
private:
std::vector<std::function<void()>> callbacks;
};
int main() {
EventHandler handler;
int x = 10;
handler.addCallback([x] {
std::cout << "事件触发,捕获的值:x = " << x << std::endl;
});
handler.trigger();
return 0;
}
程序输出:
事件触发,捕获的值:x = 10
四、Lambda 表达式的进阶用法
1. 带参数和返回值的 Lambda 表达式
Lambda 表达式可以有参数和返回值,就像普通函数一样。
#include <iostream>
int main() {
auto add = [](int a, int b) { return a + b; };
std::cout << "两数之和: " << add(3, 5) << std::endl; // 输出 8
return 0;
}
2. Lambda 表达式的递归调用
Lambda 表达式可以进行递归调用,但需要捕获自身。
#include <iostream>
int main() {
auto factorial = [&factorial](int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
};
std::cout << "5 的阶乘: " << factorial(5) << std::endl; // 输出 120
return 0;
}
3. Lambda 表达式与成员函数
Lambda 表达式可以调用类的成员函数。
#include <iostream>
#include <vector>
#include <algorithm>
class MyClass {
public:
int getValue() const { return value; }
void setValue(int v) { value = v; }
private:
int value;
};
int main() {
MyClass obj;
obj.setValue(10);
auto printValue = [&obj]() {
std::cout << "类成员函数调用:value = " << obj.getValue() << std::endl;
};
printValue(); // 输出 10
return 0;
}
总结
C++ Lambda 表达式是一种强大而灵活的工具,它允许我们在代码中直接定义匿名函数对象。通过捕获机制,Lambda 表达式可以访问外部变量,这使得它在算法库、多线程编程、回调函数等场景中非常有用。Lambda 表达式不仅可以简化代码结构,还能提高代码的可读性和可维护性。
更多推荐
所有评论(0)