c++ - Where do the elements removed by std::remove_if go? -
the reference says
template< class forwardit, class unarypredicate > forwardit remove_if( forwardit first, forwardit last, unarypredicate p );
iterators pointing elements between old , new ends of range still dereferenceable, elements have unspecified values.
i tried simple program find out mean "unspecified values".
#include <vector> #include <memory> #include <iostream> #include <algorithm> int main() { std::vector< std::shared_ptr<int> > ints; (int = 0; < 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; }); (int = 0; < 10; ++i) std::cout << *ints[i] << std::endl; return 0; }
the output is:
0 7 2 3 4 5 6 program has unexpectedly finished.
that mysterious happens data after 7th element, causes segfault.
interestingly, possible implementation here
template<class forwardit, class unarypredicate> forwardit remove_if(forwardit first, forwardit last, unarypredicate p) { forwardit result = first; (; first != last; ++first) { if (!p(*first)) { *result++ = *first; } } return result; }
does not produce segfault.
is bug? since iterators should dereferencable. using gcc 4.7.3
firstly, in case aren't aware, need remember important when use std::remove
, std::remove_if
: cannot erase elements underlying container. means don't remove anything.
you need use remove/erase idiom:
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());
what happens "erased" elements implementation defined. here gcc
implementation:
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; }
likely causing segfault fact implementation calls _glibcxx_move
.
Comments
Post a Comment