擦除不是在std :: for_each中调用,而是在基于范围的for循环中执行?

时间:2014-03-09 23:41:21

标签: c++ c++11

运行代码:

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不会改变结果。

3 个答案:

答案 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);
});

所以你只需更改副本。