template< class ForwardIt, class UnaryPredicate >
ForwardIt remove_if( ForwardIt first, ForwardIt last, UnaryPredicate p );
Iterators pointing to an elements between the old and the new ends of the range are still dereferenceable, but the elements themselves have unspecified values.
我尝试了这个简单的程序来找出“未指定的值”的含义。
#include <vector>
#include <memory>
#include <iostream>
#include <algorithm>
int main()
{
std::vector< std::shared_ptr<int> > ints;
for (int i = 0; i < 10; ++i)
ints.push_back(std::make_shared<int>(i));
std::remove_if(ints.begin(), ints.end(),
[](const std::shared_ptr<int>& element)
{
return *element % 7 != 0;
});
for (int i = 0; i < 10; ++i)
std::cout << *ints[i] << std::endl;
return 0;
}
输出是:
0
7
2
3
4
5
6
The program has unexpectedly finished.
那是第 7 个元素之后的数据发生了一些神秘的事情,这导致了段错误。
有趣的是,来自 here 的可能实现
template<class ForwardIt, class UnaryPredicate>
ForwardIt remove_if(ForwardIt first, ForwardIt last,
UnaryPredicate p)
{
ForwardIt result = first;
for (; first != last; ++first) {
if (!p(*first)) {
*result++ = *first;
}
}
return result;
}
不产生段错误。
这是一个错误吗?因为迭代器应该是可取消引用的。我正在使用 gcc 4.7.3
最佳答案
首先,以防万一您不知道,在使用 std::remove
和 std::remove_if
时需要记住一些非常重要的事情:它们 实际上无法从底层容器中删除元素。这意味着他们自己实际上并没有移除任何东西。
您需要使用类似删除/删除 惯用法的东西:
auto to_erase = std::remove_if(ints.begin(), ints.end(),
[](const std::shared_ptr<int>& element)
{
return *element % 7 != 0;
});
ints.erase(to_erase, ints.end());
“删除”元素会发生什么是实现定义的。这是 gcc
实现:
template<typename _ForwardIterator, typename _Predicate>
_ForwardIterator
remove_if(_ForwardIterator __first, _ForwardIterator __last,
_Predicate __pred)
{
// concept requirements
__glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
_ForwardIterator>)
__glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
__first = _GLIBCXX_STD_A::find_if(__first, __last, __pred);
if(__first == __last)
return __first;
_ForwardIterator __result = __first;
++__first;
for(; __first != __last; ++__first)
if(!bool(__pred(*__first)))
{
*__result = _GLIBCXX_MOVE(*__first);
++__result;
}
return __result;
}
可能导致段错误的原因是此实现调用了 _GLIBCXX_MOVE
。
关于c++ - std::remove_if 移除的元素到哪里去了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16476308/