C++ 算法与 ranges:用 find_if、transform 写清数据处理意图

C++ 算法与 ranges:用 find_if、transform 写清数据处理意图

很多循环并不复杂,只是在寻找一个元素,或者把每个元素转换成另一种值。把这种意图交给标准算法,代码通常比手动维护下标更容易检查。

最低标准:C++20。本篇同时展示传统迭代器算法与 ranges 算法。

1. 查找符合条件的元素,再生成结果

cpp 复制代码
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>

struct Item { std::string name; int price; };

int main() {
    std::vector<Item> items{{"pen", 3}, {"book", 12}, {"bag", 35}};
    auto found = std::find_if(items.begin(), items.end(),
                              [](const Item& x) { return x.price >= 10; });
    if (found != items.end()) std::cout << found->name << '\n';

    std::vector<int> doubled;
    std::ranges::transform(items, std::back_inserter(doubled),
                           [](const Item& x) { return x.price * 2; });
    for (int value : doubled) std::cout << value << ' ';
    std::cout << '\n';

    auto cheap = std::ranges::find_if(items,
        [](int price) { return price < 5; }, &Item::price);
    if (cheap != items.end()) std::cout << cheap->name << '\n';
}

输出依次为 book、6 24 70、pen。find_if 返回第一个满足条件的位置;找不到时返回结束迭代器,必须先判断再解引用。它不会把所有匹配项收集起来。

2. ranges 的投影让条件更专注

最后一次查找把 &Item::price 作为投影:算法先取得价格,再把价格交给条件函数。这样条件本身无需知道 Item 的其他字段。

ranges 版本通常可以直接接收容器,不必重复写 begin/end。不过"写法更短"不意味着生命周期问题消失。不要长期保存容器失效后的迭代器;对某些临时范围调用算法时,返回类型会使用 dangling 来阻止错误借用。

3. transform 不会自动扩大普通目标容器

若把空 vector 的 begin 作为输出位置,算法不会自动插入元素。应先 resize 到足够长度,或像示例一样使用 back_inserter。reserve 只预留容量,不会增加 size,不能替代 resize。

输入和输出的关系也要遵守算法约定:需要原地转换时,可以把输出起点设为输入起点;不要随意使用错位重叠区间。转换过程中也不应通过副作用改变正在遍历的容器结构。

4. 算法表达意图,普通循环表达流程

"找第一个""逐个转换""判断是否全部满足"很适合算法;如果每一步都有复杂状态迁移、多个退出条件和错误恢复,清晰的普通循环可能更合适。

把判断函数写成无意外副作用的小函数,避免假设 transform 的调用顺序可以承担业务流程。最终目标不是消灭 for,而是让读者一眼看出代码在做什么。

进一步阅读:Microsoft 标准算法参考。

相关推荐
一晌小贪欢10 分钟前
Python基础:第 09 篇 · while 循环:重复直到不满足
开发语言·c++·python·数据可视化·面向对象·python办公
zh_xuan17 分钟前
LeeCode 496. 下一个更大元素I
数据结构·算法·栈·单调栈
机 _ 长26 分钟前
05 智算运维|8 张卡怎么才算「捆成一张」:NCCL 实测与拓扑
运维·人工智能·算法·智算运维
xiaoye-duck42 分钟前
《C++ 项目:手写大模型接入 SDK》LLMManager架构设计与实现
开发语言·网络·c++·语言模型
一条大祥脚1 小时前
CuTe 与 CuTe DSL:从 C++ 模板元编程到 Python DSL 的 GPU 编程演进
开发语言·c++·python·cutlass·cute·cute dsl
·present·1 小时前
CSAPP(lecture 13_02 Linking)
c语言·c++
早起CaiCai1 小时前
【2023-01 OM】利用深度学习算法融合异质观测实现海洋场降尺度
人工智能·深度学习·算法
梦里寻码2 小时前
我用 NestJS + Vue3 写了一套完整的研发管理系统(58 表 / 229 API / 130 项断言,全开源
前端·后端·算法
FRing032 小时前
vue2干货总结8(路由模块封装、router-link、声明式导航、路由重定向、编程式导航)
开发语言·前端·vue.js·vue2
旖旎夜光2 小时前
【C++ 基础入门】C++ 多态(上):虚函数、重写、override/final 与抽象类
开发语言·c++·笔记·学习