std::for_each修改容器元素需用引用参数(如int&或auto&),否则仅修改副本;const容器或迭代器不可修改;string安全,vector需用auto&;map的key不可直接修改。

std::for_each 修改容器元素的常见误区
直接用 std::for_each 配合普通函数对象(比如 lambda)修改容器元素,往往无效——因为默认传入的是元素的**值拷贝**,而非引用。你改了副本,原容器没变。
典型错误写法:
std::vector<int> v = {1, 2, 3};<br>std::for_each(v.begin(), v.end(), [](int x) { x *= 2; }); // v 仍是 {1,2,3}</int>
- lambda 参数必须声明为
int&或auto&才能修改原值 - 若容器是
const或迭代器是const_iterator,则无法修改,编译失败 -
std::for_each本身不保证执行顺序,但对顺序无关的就地修改影响不大
正确写法:用引用捕获或引用参数
要真正修改元素,必须让函数对象操作的是元素的引用。最常用且安全的方式是把 lambda 参数设为左值引用:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
std::vector<int> v = {1, 2, 3};<br>std::for_each(v.begin(), v.end(), [](int& x) { x *= 2; }); // v 变成 {2,4,6}</int>
- 使用
auto&更通用:[](auto& x) { x += 10; },适配不同类型 - 避免写成
[](const int& x)—— const 引用不能赋值 - 如果需同时读取索引,
std::for_each不提供,得换std::ranges::for_each(C++20)或手动带索引遍历
std::for_each vs 范围 for 循环:什么情况下该选前者?
纯就地修改场景下,for (auto& x : container) 更简洁、易读、不易出错。那为什么还要用 std::for_each?它真正的价值在「算法语义明确 + 可组合」:
- 当你后续要接
std::bind、适配器或自定义策略时,std::for_each是标准算法接口 - 配合
std::execution::par(C++17 并行策略),可启用并行执行:std::for_each(std::execution::par, v.begin(), v.end(), [](auto& x){...}) - 若逻辑封装在独立函数对象中(比如重用的修改器),
std::for_each比 range-for 更利于解耦 - 注意:并行版本不保证顺序,修改有依赖关系的元素(如累加)会出错
修改 string 中的 char 或 vector 的坑
某些容器有特殊行为,容易踩雷:
-
std::string的operator[]返回char&,所以std::for_each(s.begin(), s.end(), [](char& c){ c = toupper(c); })是安全的 -
std::vector<bool></bool>是特化实现,operator[]返回代理对象(std::vector<bool>::reference</bool>),不是bool&;直接用[](bool& b)会编译失败,必须用[](auto& b)或显式处理代理类型 - 修改
std::map的 key 会导致未定义行为——std::for_each迭代的是std::pair<const key value>&</const>,key 部分是 const,强行 cast 去 const 极危险
真正要改 key,得先删后插,别试图绕过 const 限定。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










