std :: remove()可以正常使用文字,但不能使用取消引用的迭代器 [英] std::remove() works as expected with literal but not with dereferenced iterator

查看:86
本文介绍了std :: remove()可以正常使用文字,但不能使用取消引用的迭代器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在学习删除-惯用语的同时,以及了解std :: min_element()的工作方式如何在C ++ 17中使用std :: min_element?。我想尝试从以下代码段中删除最小元素:

While learning remove-erase idiom, as well as understanding how std::min_element() work How to use std::min_element in C++17?. I thought to try removing minimum element from the following piece of code:

#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
    std::vector<int> v{3, 1, 4, 1, 5, 9};

    std::vector<int>::iterator result = std::min_element(v.begin(), v.end());
    std::cout << "min element at: " << std::distance(v.begin(), result);
}

v中有两个最小元素。我试图用添加诊断程序

There are two minimum elements in v. I tried to remove both of them with added diagnostics

int main()
{
    std::vector<int> v{3, 1, 4, 1, 5, 9};

    std::vector<int>::iterator result = std::min_element(v.begin(), v.end());

    v.erase(result); // This removes just one minimum. What if need to remove all?

    v.push_back(1); // Okay, let's add the minimum again

    std::vector<int>::iterator another_result = std::min_element(v.begin(), v.end());

    std::cout << "min element: " << *another_result  << std::endl;

    auto iter = std::remove(std::begin(v), std::end(v), *another_result);
    // If I write 1 instead of *another_result, I manage to remove all 1's. No need to use iter-1 in erase idiom then.

    std::cout << "\nWhere is my iterator pointing? It is at: " << std::distance(v.begin(), iter);

    v.erase(iter, std::end(v)); // All the minimum are gone if I use iter-1 instead of iter and use *another_result

    std::for_each(v.begin(), v.end(), [](const int& x){std::cout << x << " ";}); // Why is still "1" there?
}

链接

我的问题是带有注释的代码中突出显示的

My questions are, as highlighted in the code with the comments,


  1. 为什么我可以通过提供文字而不是取消引用的迭代器来删除所有minimum实例?即
    为什么下面的工作?



auto iter = std::remove(std::begin(v), std::end(v), 1);

但是


  1. 如果我选择坚持使用取消引用迭代器,则



auto iter = std::remove(std::begin(v), std::end(v), *another_result);

在坚持删除擦除习惯用法的同时,不删除所有minimum实例。

Doesn't remove all the instances of minimum while sticking to remove-erase idiom.

推荐答案

如果要一次性删除所有最小值,则可以执行以下操作:

If you want to remove all the minimum values in one go, you could do something a little more odd like this:

template<class T>
void remove_min( std::vector<T> &container ) {
    if ( container.empty() ) return;
    T min_val = *std::min_element( container.begin(), container.end() );
    container.erase( std::remove( container.begin(), container.end(), min_val ), container.end() );
}

请注意, min_val 首先是副本(请参阅PeterT的答案以获取解释)。上面的内容可能可以修改为与其他容器一起使用。

Note that the min_val is a copy first (see PeterT's answer for explanation). The above can probably be modified to work with other containers.

请记住 std :: remove 不会不能真正删除任何东西。该函数的返回值将指向新的 last元素所在的位置之后,然后从该位置调用容器的 erase 方法以删除所有从那时起的元素。

Keep in mind that std::remove doesn't really remove anything. The return value from the function will point to after where the new last element would be, then call the container's erase method from there to remove all the elements from that point on.

这篇关于std :: remove()可以正常使用文字,但不能使用取消引用的迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆