运行代码:
for (auto& v : vec)
v.erase(0, v.find("\n") + 1);
做出了什么:擦除vec
的每个元素中第一个“\ n”之前的所有内容。
但是,运行代码:
std::for_each(vec.begin(), vec.end(), [&](std::string v) {
v.erase(0, v.find("\n") + 1);
});
不会删除vec
的任何元素中的任何内容。使lambda按值传递而不是-reference不会改变结果。
答案 0 :(得分:5)
std::for_each(vec.begin(), vec.end(), [&](std::string v) {
^^^^^^^^^^^^^
你正在按价值来论证。您稍后只处理副本,与容器中的原始对象无关。将lambda的参数更改为引用。同时删除捕获列表(因为您没有从当前范围捕获任何内容!)。
Lambda的捕获列表和参数列表是两种不同的野兽。捕获当前作用域的变量与通过lambda operator()
获取参数无关。
答案 1 :(得分:2)
[&]
是lambda捕获列表,它指定如何在lambda中捕获来自封闭范围的变量。它与收到v
的方式无关。如果您希望收到v
作为参考,则需要这样做:
std::for_each(vec.begin(), vec.end(), [&](std::string& v) {
v.erase(0, v.find("\n") + 1);
});
我也看不出你有什么理由捕捉任何东西,所以只需{@ 1}}制作捕捉名单。
答案 2 :(得分:1)
此代码段
for (auto& v : vec)
v.erase(0, v.find("\n") + 1);
相当于
for ( std::string& v : vec)
v.erase(0, v.find("\n") + 1);
这意味着v是对vec元素的引用。它与lambda表达式中的&符号没什么共同之处
std::for_each(vec.begin(), vec.end(), [&](std::string v) {
v.erase(0, v.find("\n") + 1);
});
您需要的所有内容都是正确指定lambda表达式中的参数,方法与基于语句
的范围相同。std::for_each(vec.begin(), vec.end(), []( std::string &v) {
v.erase(0, v.find("\n") + 1);
});
在您的代码中,lambda表达式获取原始字符串的副本。
std::for_each(vec.begin(), vec.end(), [&](std::string v) {
v.erase(0, v.find("\n") + 1);
});
所以你只需更改副本。