¿Por qué obtengo un resultado diferente si en lugar de x paso directamente el elemento de matriz ar [0] en la función std :: remove? [duplicar]

Aug 19 2020
#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;
}

¿Por qué obtengo un resultado diferente si en lugar de xpasar directamente ar[0]la std::removefunción?

xy ar[0]tienen el mismo valor.

Respuestas

3 largest_prime_is_463035818 Aug 19 2020 at 13:09

El motivo es que std::removetoma por referencia el último parámetro. Desde cppreference :

Debido a que std :: remove toma valor por referencia, puede tener un comportamiento inesperado si es una referencia a un elemento del rango [primero, último].

Es un poco complicado, porque el parámetro se pasa como constreferencia:

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

Sin embargo, el hecho de que ar[0]se pase como constreferencia no implica que ar[0]no pueda modificarse por otros medios. En este caso se modifica mediante first/ last. En realidad, no puedo pensar en un caso en el que estaría "bien" tener un elemento dentro [first, last)como value.

A modo de ilustración, considere que obtiene la misma salida incorrecta con ar[0]como si declarara xcomo referencia:

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

Aquí xse pasa como constreferencia, pero el algoritmo se modifica ar[0].