Perché ottengo un risultato diverso se invece di x passo direttamente l'elemento dell'array ar [0] nella funzione std :: remove? [duplicare]

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;
}

Perché ottengo un risultato diverso se invece di xpassare direttamente ar[0]alla std::removefunzione?

xe ar[0]hanno lo stesso valore.

Risposte

3 largest_prime_is_463035818 Aug 19 2020 at 13:09

Il motivo è che std::removeprende l'ultimo parametro per riferimento. Da cppreference :

Poiché std :: remove assume valore per riferimento, può avere un comportamento imprevisto se è un riferimento a un elemento dell'intervallo [first, last).

È un po 'complicato, perché il parametro viene passato come constriferimento:

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

Tuttavia, solo perché ar[0]viene passato come constriferimento non implica che ar[0]non possa essere modificato con altri mezzi. In questo caso viene modificato tramite first/ last. In realtà non riesco a pensare a un caso in cui sarebbe "ok" avere un elemento all'interno [first, last)come value.

A titolo illustrativo, considera che ottieni lo stesso output sbagliato con ar[0]come se avessi dichiarato xcome riferimento:

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

Qui xviene passato come constriferimento, ma l'algoritmo viene modificato ar[0].