[英]std::remove_if and erase not removing elements from std::vector
我正在练习leetcode容易出问题。 我想使用lambda从vector中删除_if(这是第一次,很棒)。 我得到了new_end的否定指针。
#include <vector>
#include <iostream>
#include <algorithm>
#include <functional> // std::greater
using namespace std;
int main()
{
vector<int> a = { 2, 7, 11, 15 };
int target = 9;
auto new_end = std::remove_if(a.begin(), a.end(), [&a, target](const int x)
{
return std::count(a.begin(), a.end(), x) > target;
});
a.erase(new_end, a.end());
return 0;
}
没有错误,但new_end是负指针值。
std::remove_if(begin, end, pred)
返回一个指向第一个元素的迭代器 ,如果没有匹配pred
元素,则擦除或end
。 在你的情况下,后者是正确的:
auto new_end = std::remove_if(a.begin(), a.end(),
[&a, target](const int x) { return std::count(a.begin(), a.end(), x) > target; }
);
new_end
等于a.end()
。 调试器将此值打印为垃圾。 但它碰巧只是偶然在你的情况下工作。
正如多个评论员所指出的,一旦你的谓词返回true
一次,范围[ a.begin()
, a.end
)就被修改,最后一个元素的值未指定1 。
这使得std::count(a.begin(), a.end(), x)
返回未指定的值。
建议的修复方法是在remove_if
开始移动之前复制a
。 这是通过按值捕获它来完成的:
auto new_end = std::remove_if(a.begin(), a.end(),
[b=a, target](const int x) { return std::count(b.begin(), b.end(), x) > target; }
);
将副本初始化为新名称b
只是强调它是副本。
1)来自std::remove_if
:
指向新逻辑结束和范围的物理结束之间的元素的迭代器仍然是可解除引用的,但元素本身具有未指定的值(根据MoveAssignable后置条件)。
我假设要从vector中删除大于9的数字,这是代码
vector<int> a = { 2, 7, 11, 15 };
int target = 9;
auto new_end = std::remove_if(a.begin(), a.end(), [](const int x)
{
return x > 9;
});
a.erase(new_end, a.end());
return 0;
lambda参数'x'将由remove_if
提供,您不需要在捕获列表中添加任何内容
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.