Pourquoi est-ce que j'obtiens un résultat différent si au lieu de x je passe directement l'élément de tableau ar [0] dans la fonction std :: remove? [dupliquer]

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

Pourquoi est-ce que j'obtiens un résultat différent si au lieu de xpasser directement ar[0]la std::removefonction?

xet ar[0]ont la même valeur.

Réponses

3 largest_prime_is_463035818 Aug 19 2020 at 13:09

La raison en est que std::removeprend le dernier paramètre par référence. De cppreference :

Étant donné que std :: remove prend une valeur par référence, il peut avoir un comportement inattendu s'il s'agit d'une référence à un élément de la plage [premier, dernier).

C'est un peu délicat, car le paramètre est passé comme constréférence:

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

Cependant, le simple fait de ar[0]passer comme constréférence n'implique pas que ar[0]cela ne puisse pas être modifié par d'autres moyens. Dans ce cas, il est modifié via first/ last. En fait, je ne peux pas penser à un cas où il serait "ok" d'avoir un élément à l'intérieur [first, last)comme value.

Par exemple, considérez que vous obtenez la même sortie erronée avec ar[0]comme si vous aviez déclaré xcomme référence:

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

Ici xest passé comme constréférence, mais l'algorithme modifie ar[0].