我正在练习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是负指针值。
答案 0 :(得分:2)
std::remove_if(begin, end, pred)
返回指向要删除的第一个元素的迭代器,如果没有匹配end
的元素,则返回pred
。在你的情况下,后者是正确的:
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()
。调试器将此值打印为垃圾。但在你的情况下偶然it happens to just works。
正如多位评论员指出的那样,一旦您的谓词返回true
一次,范围[a.begin()
,a.end
)就会被修改,而最后一个元素的值未指定 1
这会使std::count(a.begin(), a.end(), x)
返回未指定的值。
建议的解决方法是在a
开始移动之前制作remove_if
的副本。这是通过按值捕获它来完成的:
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后置条件)。
答案 1 :(得分:-2)
我假设要从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论证&#39; x&#39;将由remove_if
提供,您不需要在捕获列表中添加任何内容