C++ std::remove_移除的元素在哪里?
报告说C++ std::remove_移除的元素在哪里?,c++,gcc,stl,C++,Gcc,Stl,报告说 template< class ForwardIt, class UnaryPredicate > ForwardIt remove_if( ForwardIt first, ForwardIt last, UnaryPredicate p ); 第7个元素之后的数据发生了一些神秘的事情,这导致了segfault 有趣的是,从 模板 ForwardIt remove_如果(ForwardIt first,ForwardIt last, 一元谓词(p) { ForwardIt
template< class ForwardIt, class UnaryPredicate >
ForwardIt remove_if( ForwardIt first, ForwardIt last, UnaryPredicate p );
第7个元素之后的数据发生了一些神秘的事情,这导致了segfault
有趣的是,从
模板
ForwardIt remove_如果(ForwardIt first,ForwardIt last,
一元谓词(p)
{
ForwardIt结果=第一;
for(;first!=last;++first){
如果(!p(*第一个)){
*结果+=*第一;
}
}
返回结果;
}
不会产生segfault
这是虫子吗?因为迭代器应该是可解引用的。我使用的是GCC4.7.3迭代器可能是可解引用的,但共享指针可能不是。在取消引用具有未指定值的共享指针之前,您应该检查是否为空。首先,如果您不知道,在使用
std::remove
和std::remove\u时,您需要记住一些非常重要的内容,如果:它们实际上无法从底层容器中删除元素。这意味着它们自己实际上并不移除任何东西
您需要使用类似“删除/擦除”的习惯用法:
可能导致SEGFULT的原因是,此实现调用了\u GLIBCXX\u MOVE
如果可能,C++11编译器将使用移动语义来移动未被std::remove\u if
删除的元素。移动共享\u ptr会使原始共享\u ptr对象为空(它不再拥有指针)-对该原始共享\u ptr调用get()
将返回空指针
因此,如果取消引用该共享\u ptr,将得到一个空指针取消引用
总之,虽然迭代器仍然是可取消引用的,但共享的\u ptr可能不是。但是您认为数据发生了什么变化?如果实现如此简单。在它们的实现中使用移动语义会导致这样的行为吗?我甚至没有想到“数据发生了什么”。共享指针的值不是契约的一部分,所以我根本不关心它们。可能会移动范围的成员,从而导致空的共享指针,或者可能是“老式”的就地析构函数和复制构造,而不是赋值。您应该能够在系统上找到std::remove_if
的源代码(因为它是一个模板)来验证这一点。“它们无法修改基础容器”。事实并非如此。它们确实修改了容器,因为操作的结果是元素被重新排列。他们不能做的是减少容器的大小(即<代码>容器)。(代码)>代码> STD::ReaveVII:< /C> >,只有一些元素(由操作删除)未按照C++标准指定。“纳瓦兹的措辞很差。我已经重新回答了我的答案。C++标准算法不适用于容器。它们适用于序列。容器是序列的一个来源,但不是唯一的来源。明白了-使用remove\u if
小心地使用erase
。如果您忘记使用此向量中的范围擦除,即v.erase(如果(…),v.end())
,只需键入v.erase(如果(…))
-这将只擦除第一个元素。之后,您将得到无效的共享\u ptr
s。
#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.
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;
}
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());
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;
}