简体   繁体   English

std :: remove_if并擦除不从std :: vector中删除元素

[英]std::remove_if and erase not removing elements from std::vector

I am practicing leetcode easy problem. 我正在练习leetcode容易出问题。 I want to remove_if from an vector using lambda (for the first time, It is great). 我想使用lambda从vector中删除_if(这是第一次,很棒)。 I get a negative pointer for new_end. 我得到了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;
}

There is no error but new_end is a negative pointer value. 没有错误,但new_end是负指针值。

在此输入图像描述

std::remove_if(begin, end, pred) returns an iterator pointing at the first element to erase or end if there is no element matching pred . std::remove_if(begin, end, pred)返回一个指向第一个元素的迭代器 ,如果没有匹配pred元素,则擦除或end The later is true in your case: 在你的情况下,后者是正确的:

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 equals a.end() . new_end等于a.end() This value is printed as garbage by your debugger. 调试器将此值打印为垃圾。 But it happens to just works by chance in your case. 它碰巧只是偶然在你的情况下工作。

As pointed out by multiple commentators, once your predicate has returned true once, the range [ a.begin() , a.end ) is modified and the last element has an unspecified value 1 . 正如多个评论员所指出的,一旦你的谓词返回true一次,范围[ a.begin()a.end )就被修改,最后一个元素的值未指定1

This makes std::count(a.begin(), a.end(), x) return unspecified values. 这使得std::count(a.begin(), a.end(), x)返回未指定的值。


A suggested fix is to make a copy of a before remove_if starts to move things around. 建议的修复方法是在remove_if开始移动之前复制a This is done by capturing it by value: 这是通过按值捕获它来完成的:

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

Initializing the copy to a new name b simply emphasizes that it is a copy. 将副本初始化为新名称b只是强调它是副本。


1) From std::remove_if : 1)来自std::remove_if

Iterators pointing to an element between the new logical end and the physical end of the range are still dereferenceable, but the elements themselves have unspecified values (as per MoveAssignable post-condition). 指向新逻辑结束和范围的物理结束之间的元素的迭代器仍然是可解除引用的,但元素本身具有未指定的值(根据MoveAssignable后置条件)。

I assume to want to remove numbers greater than 9 from vector, Here is the code 我假设要从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;

The lambda argument 'x' will be provided by remove_if , you don't need to add anything in the capture list lambda参数'x'将由remove_if提供,您不需要在捕获列表中添加任何内容

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM