Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ std::remove_移除的元素在哪里?_C++_Gcc_Stl - Fatal编程技术网

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