Q:

Where do the elements removed by std::remove_if go?

The reference says that 
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.

I tried this simple program to find out what they mean by "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;
}

The output is:
0
7
2
3
4
5
6
The program has unexpectedly finished.

That is something mysterious happens to the data after the 7th element, which causes a segfault.
Interestingly, the possible implementation from 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;
}

Does not produce the segfault.
Is this a bug? Since the iterators should be dereferencable. I am using gcc 4.7.3

A:

Firstly, in case you aren't aware, you need to remember something very important when you use std::remove and std::remove_if: they cannot actually erase elements from the underlying container. This means that they themselves don't actually remove anything.
You need to use something like the 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 to "erased" elements is implementation defined. Here is the 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 what is causing the segfault is the fact that this implementation calls _GLIBCXX_MOVE.

A:

The iterators may be dereferenceable but the shared pointers might not be. You should check for nullness before dereferencing a shared pointer with an unspecified value.

A:

A C++11 compiler will use move semantics if possible to move the elements that are not 'removed' by std::remove_if.  Moving a shared_ptr leaves the original shared_ptr object empty (it no longer owns a pointer) - calling get() on that original shared_ptr will return a null pointer.
Therefore if you dereference that shared_ptr, you'll get a null pointer dereference.
So, in summary, while the iterator is still dereferenceable, the shared_ptr might not be.

