Почему я получаю другой результат, если вместо x я напрямую передаю элемент массива ar [0] в функцию std :: remove? [дубликат]

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

Почему я получить другой результат , если вместо того , чтобы xя непосредственно передать ar[0]в std::removeфункцию?

xи ar[0]имеют одинаковую ценность.

Ответы

3 largest_prime_is_463035818 Aug 19 2020 at 13:09

Причина в том, что std::removeпоследний параметр берется по ссылке. Из cppreference :

Поскольку std :: remove принимает значение по ссылке, он может иметь неожиданное поведение, если это ссылка на элемент диапазона [first, last).

Это немного сложно, потому что параметр передается как constссылка:

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

Однако то, что ar[0]передается как constссылка, не означает, что ar[0]его нельзя изменить другими способами. В этом случае он изменяется через first/ last. На самом деле я не могу представить себе случая, когда было бы «нормально» иметь элемент внутри [first, last)as value.

Для иллюстрации представьте, что вы получаете такой же неправильный результат, ar[0]как если бы вы объявили xв качестве ссылки:

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

Здесь xпередается как constссылка, но алгоритм изменяется ar[0].