导读:本期聚焦于小伙伴创作的《STL算法库中有哪些常用遍历方法 for_each与transform的典型应用怎么写》,敬请观看详情。把容器里的每个元素都处理一遍,该选for_each还是transform?二者虽然都能遍历,但语义和返回值完全不同。for_each侧重副作用,比如打印或修改原容器;transform强调映射,把输入序列转换成新序列。本文用具体代码说明它们在vector、自定义类型上的用法,并比较何时该用哪一个,避免写出既难读又易错的遍历逻辑。

在C++标准模板库里,遍历容器元素是最基础也最高频的操作。除了手写循环,算法库提供了多种通用遍历工具,其中for_eachtransform最为常用。二者接口相似,却承担不同的设计意图:一个关注过程动作,一个关注数据变换。

STL算法库中有哪些常用遍历方法 for_each与transform的典型应用怎么写

for_each的典型应用

for_each接受一对迭代器和一个可调用对象,依次把每个元素传给该对象。它的返回值是传入的函数对象,因此适合执行打印、修改原元素、累加等带副作用的操作。由于直接操作原容器,不需要额外空间,在仅需处理而不产生新序列时非常直观。

下面示例用for_each将vector中所有整数加倍,并打印结果:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> nums = {1, 2, 3, 4};
    // 使用lambda修改原容器元素
    std::for_each(nums.begin(), nums.end(), [](int& n) {
        n *= 2;
    });
    // 再次遍历打印
    std::for_each(nums.begin(), nums.end(), [](int n) {
        std::cout << n << " ";
    });
    return 0;
}

上述代码第一个lambda通过引用捕获参数,直接改写原vector;第二个lambda仅做输出。可以看到,for_each并不关心返回值,重点在于“对每个元素做什么”。如果遍历目的是触发行为而非生成新数据,它比手写for更简洁且语义清晰。

需要注意的是,若lambda内部有复杂状态,可将其定义为有成员变量的函数对象,利用for_each的返回值取回状态,例如统计满足条件的个数。但总体上,它不适合用来构建新容器。

transform的典型应用

transform用于将一个序列映射为另一个序列。它有两种重载:单序列变换与双序列二元运算。结果写入由输出迭代器指定的目标位置,因此可以原地处理,也可以输出到新容器。它的核心是“输入到输出的映射关系”,强调不可变转换。

以下代码把整数向量平方后存入新向量:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> src = {1, 2, 3, 4};
    std::vector<int> dst(src.size());
    std::transform(src.begin(), src.end(), dst.begin(), [](int n) {
        return n * n;
    });
    for (int v : dst) {
        std::cout << v << " ";
    }
    return 0;
}

这里transform读取src每个元素,经lambda计算后写入dst。若想原地修改,只需把输出迭代器设为src.begin()。与for_each不同,它明确要求返回新值,编译器会强制你表达映射逻辑,从而减少隐式修改带来的bug。

双序列版本可合并两个向量,例如对应元素相加:

#include <vector>
#include <algorithm>

int main() {
    std::vector<int> a = {1, 2, 3};
    std::vector<int> b = {10, 20, 30};
    std::vector<int> c(a.size());
    std::transform(a.begin(), a.end(), b.begin(), c.begin(),
        [](int x, int y) { return x + y; });
    return 0;
}

二者差异与选型建议

从语义看,for_each是“做动作”,transform是“算新值”。若操作会改变原对象状态或无返回值,选for_each;若要把A序列变成B序列,选transform。误用会导致代码意图模糊,比如用for_each内部push_back到另一个容器,虽能跑却违背其设计。

性能上二者都属线性复杂度,差别主要在表达力。下表简要对比:

算法输入输出典型用途
for_each单序列无(副作用)打印、修改原值、触发事件
transform单或双序列新序列类型转换、数值映射、合并

实际工程中,配合lambda和范围库(C++20 ranges)能进一步精简遍历代码。但理解这两个算法的根本区别,是写出可读且健壮STL代码的前提。

自定义类型中的实践

对于自定义结构体,同样适用。假设有表示学生的结构,需要用for_each输出姓名,用transform提取成绩列表:

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>

struct Student {
    std::string name;
    int score;
};

int main() {
    std::vector<Student> list = {
        {"Alice", 90}, {"Bob", 85}
    };
    std::for_each(list.begin(), list.end(), [](const Student& s) {
        std::cout << s.name << "n";
    });
    std::vector<int> scores(list.size());
    std::transform(list.begin(), list.end(), scores.begin(),
        [](const Student& s) { return s.score; });
    return 0;
}

这段代码清晰展示了二者分工:遍历动作与数据投影解耦。当容器元素变复杂时,这种显式区分能降低维护成本。建议在团队代码中明确约定,避免混用造成逻辑隐蔽。

for_eachtransformSTL遍历修改时间:2026-08-11 13:03:42

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。