C++ 函数式编程:现代特性与示例
函数式编程(FP)是一种将计算视为数学函数求值的编程范式,它避免改变状态和可变数据。尽管C++传统上与面向对象和过程式编程相关联,但从C++11开始,特别是在C++14/17/20中,该语言已经获得了用于函数式风格的强大工具。在本文中,我们将分解关键概念,这些概念将使您的C++代码更加简洁、安全和富有表现力。
1. Lambda表达式与闭包
Lambda表达式是可以内联使用的匿名函数。它们成为C++中函数式编程的基础。Lambda从其环境中捕获变量(闭包),并且可以传递给STL算法。
Lambda表达式语法
auto lambda = [capture](parameters) -> return_type { body };示例:使用Lambda进行排序
#include <iostream>#include <vector>#include <algorithm>
int main() { std::vector<int> nums = {5, 2, 8, 1, 9}; // Sort in descending order std::sort(nums.begin(), nums.end(), [](int a, int b) { return a > b; }); for (int n : nums) std::cout << n << " "; // 9 8 5 2 1 return 0;}闭包:按值捕获和按引用捕获
#include <iostream>#include <vector>#include <algorithm>
int main() { int threshold = 5; std::vector<int> data = {1, 6, 3, 8, 2}; // Capture by value [=] - copy of threshold auto count_greater = std::count_if(data.begin(), data.end(), [=](int x) { return x > threshold; }); // Capture by reference [&] - can modify auto modify = [&](int &x) { if (x < threshold) x += threshold; }; std::for_each(data.begin(), data.end(), modify); std::cout << "Count: " << count_greater << ""; // Count: 2 for (int n : data) std::cout << n << " "; // 6 6 8 8 7 return 0;}2. 仿函数与std::function
仿函数是重载了operator()运算符的类对象。它们可以存储状态,并且行为类似于函数。std::function是一个多态包装器,用于存储任何可调用对象。
仿函数示例
#include <iostream>
class Adder {private: int base;public: Adder(int b) : base(b) {} int operator()(int x) const { return base + x; }};
int main() { Adder add5(5); std::cout << add5(10) << ""; // 15 std::cout << add5(20) << ""; // 25 return 0;}std::function:通用包装器
#include <iostream>#include <functional>#include <vector>
void process(const std::vector<int>& data, std::function<bool(int)> predicate) { for (int x : data) { if (predicate(x)) std::cout << x << " "; } std::cout << "";}
int main() { std::vector<int> numbers = {1, 2, 3, 4, 5, 6}; // Can pass lambdas process(numbers, [](int n) { return n % 2 == 0; }); // 2 4 6 process(numbers, [](int n) { return n > 3; }); // 4 5 6 // And functors struct GreaterThan { int limit; bool operator()(int n) const { return n > limit; } }; process(numbers, GreaterThan{4}); // 5 6 return 0;}3. 函数式风格的STL算法
STL库提供了许多与Lambda和仿函数完美配合的算法。不要使用循环,而是使用std::transf