C++ lambda配合remove_if删除元素时捕获变量无法获取正确值问题
问题原因
你的代码拿不到正确的fieldToRemove值,核心问题出在lambda的捕获逻辑上:
- 你写的
[fieldName, fieldToRemove]是值捕获,lambda内部会生成这两个变量的私有副本,你在lambda里给fieldToRemove赋值,修改的只是lambda内部的副本,外层定义的fieldToRemove自始至终都没被改动过,等remove_if执行结束,lambda内部的副本就随lambda对象销毁了,外层变量自然拿不到结果。 - 另外你代码里还有个笔误:
Foo结构体里没有fieldName成员,你实际要判断的字段是name,原代码的field.fieldName是无法编译通过的。 - 你加的
mutable关键字,作用只是允许你修改lambda内部的值捕获副本,解决不了副本和外层变量不互通的问题。
可实现的修正方式
方式1:保留remove_if逻辑,改为引用捕获
如果你的需求是删除所有匹配fieldName的元素,同时拿到被删的元素,只需要把fieldToRemove的捕获方式改成引用捕获即可,同时建议lambda参数传const引用,避免不必要的结构体拷贝:
Foo fieldToRemove; m_groupByFields.erase( std::remove_if( m_groupByFields.begin(), m_groupByFields.end(), [fieldName, &fieldToRemove](const Foo& field) { if (field.name == fieldName) { fieldToRemove = field; return true; } return false; } ), m_groupByFields.end() );
注意:如果vector里存在多个name匹配fieldName的元素,最终fieldToRemove存储的是遍历过程中最后一个匹配到的元素,因为remove_if会走完整个容器的遍历,后续匹配项的赋值会覆盖之前的值。
方式2:仅删除第一个匹配元素时用find_if更合理
如果你本来就只需要删除第一个符合条件的元素,用std::find_if比remove_if逻辑更清晰,性能也更好,不需要遍历整个容器:
auto matchIter = std::find_if( m_groupByFields.begin(), m_groupByFields.end(), [fieldName](const Foo& field) { return field.name == fieldName; } ); Foo fieldToRemove; if (matchIter != m_groupByFields.end()) { fieldToRemove = *matchIter; m_groupByFields.erase(matchIter); }
内容的提问来源于stack exchange,提问作者Igor
相关产品推荐
相关产品推荐

