C++函数式编程:从入门到精通——实践指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

C++函数式编程:从入门到精通



许多熟悉Python或JavaScript的开发者已经习惯了函数式编程的强大工具:lambda、map、filter、reduce。但您是否知道,C++为函数式风格提供了同样灵活的能力?在本文中,我们将从基本概念到高级技术全面解析C++中的函数式编程。您将学习如何利用C++11/14/17的现代特性编写更简洁、更安全、更具表现力的代码。



1. 函数式方法基础:lambda表达式与std::function



C++中的函数式编程始于lambda表达式。它们允许在使用点直接创建匿名函数。lambda的语法很简单:



// 基本lambdaauto sum = [](int a, int b) -> int { return a + b; };std::cout << sum(5, 3); // 8

// 带变量捕获的lambdaint multiplier = 3;auto multiply = [multiplier](int x) { return x * multiplier; };std::cout << multiply(7); // 21


lambda的关键特性是上下文捕获。您可以按值([=])、按引用([&])或组合方式捕获变量。这是闭包的基础,而闭包是函数式风格的基石。



为了存储和传递lambda,使用std::function——可调用对象的多态包装器:



#include <functional>

std::function<int(int, int)> operation;

operation = [](int a, int b) { return a + b; };std::cout << operation(10, 20); // 30

operation = [](int a, int b) { return a * b; };std::cout << operation(10, 20); // 200


提示:如果不需要将lambda存储为类型,请使用auto。std::function会带来少量开销,因此仅在需要多态性时才使用它。



2. STL算法:亲手实现map、filter、reduce



C++没有像Python那样内置的map、filter、reduce函数,但STL提供了强大的算法来替代它们。让我们看看主要的:



2.1. Map——元素转换

使用std::transform替代map:



#include <algorithm>#include <vector>

std::vector<int> numbers = {1, 2, 3, 4, 5};std::vector<int> squares(numbers.size());

std::transform(numbers.begin(), numbers.end(), squares.begin(), [](int n) { return n * n; });// squares: {1, 4, 9, 16, 25}


2.2. Filter——按条件过滤

filter的替代是std::copy_if或std::remove_if(随后删除):



std::vector<int> numbers = {1, 2, 3, 4, 5, 6};std::vector<int> evens;

std::copy_if(numbers.begin(), numbers.end(), std::back_inserter(evens), [](int n) { return n % 2 == 0; });// evens: {2, 4, 6}


2.3. Reduce——集合折叠

对于reduce,使用<numeric>中的std::accumulate:



#include <numeric>

std::vector<int> numbers = {1, 2, 3, 4, 5};int sum = std::accumulate(numbers.begin(), numbers.end(), 0, [](int acc, int n) { return acc + n; });// sum = 15


高级示例:组合map、filter和reduce来处理数据:



std::vector<std::string> names = {"Alice", "Bob", "Charlie", "David"};// 获取以'A'或'C'开头的名字的长度总和int result = std::accumulate(names.begin(), names.end(), 0,    [](int acc, const std::string& name) {        if (name[0] == 'A' || name[0] == 'C') {            return acc + name.length();        }        return acc;                

博客

书籍推荐