'How C char is different from C++ string element accessed using index

I am using C++ erase remove idiom and facing a weird problem. If I access element using string index result is not as expected.

   string str = "A man, a plan, a canal: Panama";
   str.erase(remove(str.begin(), str.end(), str[1]), str.end());

Result : Aman, a plan, a canal: Panaa

and if I use as below, result is as expected.

   string str = "A man, a plan, a canal: Panama";
   str.erase(remove(str.begin(), str.end(), ' '), str.end());

Result : Aman,aplan,acanal:Panama



Solution 1:[1]

Look at the signature of std::remove:

template< class ForwardIt, class T >
ForwardIt remove( ForwardIt first, ForwardIt last, const T& value );

The value is passed by const reference, therefore after removing first space your str[1] points to a wrong memory. It's unsafe to access container elements while modifying the container.

Solution 2:[2]

The algorithm std::remove is declared the following way

template<class ForwardIterator, class T>
ForwardIterator remove(
    ForwardIterator first, ForwardIterator last,
    const T& value // <-- reference!
);

As you can see the third parameter is declared as a reference const T& value.

So in this call

str.erase(remove(str.begin(), str.end(), str[1]), str.end());

the third argument is a reference to the object str[1] the value of which is changed within the algorithm to the letter 'm' when the first character ' ' is encountered..

If you would write for example

str.erase(remove(str.begin(), str.end(), str[1] + 0), str.end());

you would get the expected result because in this case the reference refers to a temporary object.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Genjutsu
Solution 2 Aconcagua