std :: remove()可以正常使用文字,但不能使用取消引用的迭代器 [英] std::remove() works as expected with literal but not with dereferenced iterator
问题描述
在学习删除-惯用语的同时,以及了解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,
- 为什么我可以通过提供文字而不是取消引用的迭代器来删除所有minimum实例?即
为什么下面的工作?
auto iter = std::remove(std::begin(v), std::end(v), 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屋!