C++函数式编程讲座:Lambda表达式与高阶函数
欢迎来到今天的C++函数式编程讲座!今天我们将探讨两个非常重要的概念:Lambda表达式和高阶函数。如果你对C++的印象还停留在“指针满天飞”的时代,那么今天的课程会让你重新认识这门语言的现代魅力。
讲座大纲
- Lambda表达式的起源与语法
- 高阶函数的基本概念
- Lambda与高阶函数的结合使用
- 实战演练:代码示例
- 总结与展望
1. Lambda表达式的起源与语法
起源:为什么需要Lambda?
在传统的C++中,如果想传递一个函数作为参数(比如给std::sort
),我们通常需要定义一个独立的函数或者使用函数指针。这种方式虽然有效,但不够灵活,尤其是在需要快速实现简单逻辑时显得繁琐。
为了解决这个问题,C++11引入了Lambda表达式,允许我们在代码中直接定义匿名函数。
Lambda的基本语法
Lambda表达式的语法可以分为以下几个部分:
- 捕获列表:决定Lambda如何访问外部变量。
- 参数列表:类似于普通函数的参数列表。
- 返回类型(可选):如果不显式指定,编译器会自动推导。
- 函数体:执行的具体逻辑。
语法格式如下:
[capture](parameters) -> return_type { body }
示例:简单的Lambda表达式
下面是一个简单的例子,展示如何使用Lambda计算两个数的和:
#include <iostream>
int main() {
auto add = [](int a, int b) -> int { return a + b; };
std::cout << "3 + 4 = " << add(3, 4) << std::endl;
return 0;
}
捕获列表详解
捕获列表决定了Lambda是否可以访问外部变量以及如何访问。常见的捕获方式包括:
[=]
:按值捕获所有外部变量。[&]
:按引用捕获所有外部变量。[x, &y]
:混合捕获,x
按值捕获,y
按引用捕获。
示例代码:
#include <iostream>
int main() {
int x = 10, y = 20;
auto lambda = [x, &y]() {
std::cout << "x (by value): " << x << std::endl;
std::cout << "y (by reference): " << y << std::endl;
y = 30; // 修改外部变量y
};
lambda();
std::cout << "Modified y: " << y << std::endl;
return 0;
}
2. 高阶函数的基本概念
什么是高阶函数?
高阶函数是指接受函数作为参数或返回函数作为结果的函数。这种设计思想来源于函数式编程语言(如Haskell、Lisp等),但在C++中同样适用。
C++中的高阶函数
C++标准库提供了许多内置的高阶函数,例如:
std::for_each
:对容器中的每个元素应用一个函数。std::transform
:将容器中的元素通过函数转换为新值。std::sort
:根据自定义比较函数对容器进行排序。
示例:使用std::for_each
以下代码展示了如何使用std::for_each
和Lambda表达式打印容器中的元素:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
std::for_each(numbers.begin(), numbers.end(), [](int n) {
std::cout << n << " ";
});
std::cout << std::endl;
return 0;
}
3. Lambda与高阶函数的结合使用
场景:过滤和转换数据
假设我们有一个整数列表,需要筛选出大于3的数字,并将其平方后存储到新列表中。我们可以结合std::copy_if
和std::transform
来实现这一功能。
代码示例:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
std::vector<int> result;
// 筛选出大于3的数字
std::copy_if(numbers.begin(), numbers.end(), std::back_inserter(result), [](int n) {
return n > 3;
});
// 将筛选后的数字平方
std::transform(result.begin(), result.end(), result.begin(), [](int n) {
return n * n;
});
// 输出结果
for (int n : result) {
std::cout << n << " ";
}
std::cout << std::endl;
return 0;
}
场景:自定义排序
使用Lambda表达式可以轻松实现复杂的排序规则。例如,按字符串长度降序排序:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<std::string> words = {"apple", "banana", "cherry", "date"};
std::sort(words.begin(), words.end(), [](const std::string& a, const std::string& b) {
return a.size() > b.size();
});
for (const auto& word : words) {
std::cout << word << " ";
}
std::cout << std::endl;
return 0;
}
4. 实战演练:代码示例
练习1:实现一个简单的计算器
目标:编写一个程序,支持加法、减法、乘法和除法操作。用户可以选择操作符并输入两个数字。
解决方案:
#include <iostream>
#include <functional>
int main() {
double num1, num2;
char op;
std::cout << "Enter number1 operator number2: ";
std::cin >> num1 >> op >> num2;
std::function<double(double, double)> operation;
switch (op) {
case '+': operation = [](double a, double b) { return a + b; }; break;
case '-': operation = [](double a, double b) { return a - b; }; break;
case '*': operation = [](double a, double b) { return a * b; }; break;
case '/': operation = [](double a, double b) { return b != 0 ? a / b : 0; }; break;
default: std::cout << "Invalid operator"; return 1;
}
std::cout << "Result: " << operation(num1, num2) << std::endl;
return 0;
}
练习2:统计单词频率
目标:读取一段文本,统计每个单词出现的次数。
解决方案:
#include <iostream>
#include <sstream>
#include <map>
#include <algorithm>
int main() {
std::string text;
std::cout << "Enter text: ";
std::getline(std::cin, text);
std::map<std::string, int> wordCount;
std::istringstream stream(text);
std::string word;
while (stream >> word) {
++wordCount[word];
}
for (const auto& pair : wordCount) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}
5. 总结与展望
今天我们学习了C++中的Lambda表达式和高阶函数,它们为函数式编程提供了强大的支持。通过Lambda表达式,我们可以更简洁地定义匿名函数;通过高阶函数,我们可以更灵活地处理数据。
未来的C++版本(如C++20和C++23)将继续扩展这些功能,例如引入更强大的范围库(Ranges Library)和协程(Coroutines)。让我们期待更多令人兴奋的变化吧!
最后,用一句来自Bjarne Stroustrup(C++之父)的话结束今天的讲座:
"C++ is designed to allow you to express ideas that you cannot express in other languages."
谢谢大家的聆听!如果有任何问题,请随时提问。