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

Popular posts from this blog

linux - xterm copying to CLIPBOARD using copy-selection causes automatic updating of CLIPBOARD upon mouse selection -

c++ - qgraphicsview horizontal scrolling always has a vertical delta -