4
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>

using namespace std;

int main()
{
    vector<int> ar = {1, 2, 2, 2, 3, 4, 5, 5, 5, 6, 7};
    vector<int> sum;
    int n = ar.size();
    for (int i = 0; i < n; i++)
    {
        int x = ar[0];
        int frq = count(ar.begin(), ar.end(), x);
        int q = frq / 2;
        sum.push_back(q);

        ar.erase(remove(ar.begin(), ar.end(), x), ar.end()); // Doubt
    }
    int count = 0;
    int n1 = sum.size();
    for (int i = 0; i < n1; i++)
    {
        count = count + sum[i];
    }
    cout << count;
}

Why do I get a different result if instead of x I directly pass ar[0] in the std::remove function?

x and ar[0] have the same value.

1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
saurov deb
  • 41
  • 2

1 Answers1

3

The reason is that std::remove takes the last parameter by reference. From cppreference:

Because std::remove takes value by reference, it can have unexpected behavior if it is a reference to an element of the range [first, last).

It is a bit tricky, because the paramter is passed as const reference:

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

However, just because ar[0] is passed as const reference does not imply that ar[0] cannot be modified by other means. In this case it is modified through first / last. Actually I cannot think of a case where it would be "ok" to have an element inside [first, last) as value.

For illustration, consider that you get the same wrong output with ar[0] as if you declared x as a reference:

int& x=ar[0];
ar.erase(remove(ar.begin(),ar.end(),x),ar.end());

Here x is passed as const reference, but the algorithm does modify ar[0].

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • 1
    I wonder what "unexpected" means. Is it "undefined" or "unspecified"? Can't find it in the [reference](https://eel.is/c++draft/alg.remove). – cigien Aug 19 '20 at 13:16
  • 1
    @cigien I was wondering the same, didnt check the standard. I find the text on cppref a bit misleading "Removes all elements that are equal to value, using operator== to compare them." that sounds as if order of those comparisons wouldnt matter at all, but it does. On the other hand I wouldnt be too surprised if the standard does not specifically mentions this case – 463035818_is_not_an_ai Aug 19 '20 at 13:19
  • @cigien, [in this duplicate thread](https://stackoverflow.com/a/59348038/6865932) there is a discussion about the same matter. – anastaciu Aug 19 '20 at 13:29
  • @anastaciu interesting, but make sure to read till the end, turns out that eventually it was agreed that there is no UB – 463035818_is_not_an_ai Aug 19 '20 at 13:31
  • @idclev463035818, yes. – anastaciu Aug 19 '20 at 13:33
  • 1
    @idclev463035818 but "there doesn't appear to be any UB here" is definitely not a smoking gun. – anastaciu Aug 19 '20 at 13:34