Mengapa saya mendapatkan hasil yang berbeda jika alih-alih x saya langsung meneruskan elemen array ar [0] dalam fungsi std :: remove? [duplikat]

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

Mengapa saya mendapatkan hasil yang berbeda jika bukan xsaya langsung lulus ar[0]di std::removefungsi?

xdan ar[0]memiliki nilai yang sama.

Jawaban

3 largest_prime_is_463035818 Aug 19 2020 at 13:09

Alasannya adalah karena std::removemengambil parameter terakhir sebagai referensi. Dari cppreference :

Karena std :: remove mengambil nilai dengan referensi, ia bisa memiliki perilaku yang tidak terduga jika ia merujuk ke elemen rentang [pertama, terakhir).

Agak rumit, karena parameter diteruskan sebagai constreferensi:

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

Namun, hanya karena ar[0]diteruskan sebagai constreferensi tidak berarti bahwa ar[0]tidak dapat dimodifikasi dengan cara lain. Dalam hal ini diubah melalui first/ last. Sebenarnya saya tidak dapat memikirkan kasus di mana akan "baik" untuk memiliki elemen di dalamnya [first, last)sebagai value.

Sebagai ilustrasi, pertimbangkan bahwa Anda mendapatkan keluaran yang salah yang sama ar[0]seperti jika Anda menyatakan xsebagai referensi:

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

Ini xditeruskan sebagai constreferensi, tetapi algoritme memang memodifikasi ar[0].