Ini kode saya:
while (it!=s.end()) //here 's' is a set of stl and 'it' is iterator of set
{
*it=*it-sub; //'sub' is an int value
it++;
}
Saya tidak dapat memperbarui nilai yang ditetapkan oleh iterator. Saya ingin mengurangi nilai integer 'sub' dari semua elemen set.
Adakah yang bisa membantu saya di mana masalah sebenarnya dan apa solusi yang sebenarnya?
Ini pesan kesalahannya:
error: assignment of read-only location ‘it.std::_Rb_tree_const_iterator<int>::operator*()’
28 | *it=*it-sub;
| ~~~^~~~~~~~
*it - sub
. Harap perhatikan bahwastd::set::erase()
mengembalikan iterator baru yang harus digunakan dalam kasus Anda agarwhile
loop tetap berfungsi dengan baik.Jawaban:
Nilai-nilai kunci elemen dalam
std::set
adalahconst
untuk alasan yang bagus. Mengubah mereka dapat merusak urutan yang penting untuk astd::set
.Oleh karena itu, solusinya adalah menghapus iterator dan memasukkan yang baru dengan kunci
*it - sub
. Harap perhatikan bahwastd::set::erase()
mengembalikan iterator baru yang harus digunakan dalam kasus Anda agar loop sementara berfungsi dengan baik.Keluaran:
Demo langsung di coliru
Perubahan pada
std::set
saat iterasi itu bukan masalah secara umum tetapi dapat menyebabkan masalah halus.Fakta yang paling penting adalah bahwa semua iterator yang digunakan harus tetap utuh atau tidak dapat digunakan lagi. (Itulah sebabnya iterator saat ini dari elemen erase ditetapkan dengan nilai pengembalian
std::set::erase()
yang mana merupakan iterator utuh atau akhir set.)Tentu saja, elemen dapat dimasukkan juga di belakang iterator saat ini. Meskipun ini bukan masalah mengenai hal
std::set
itu dapat memutus loop dari contoh saya di atas.Untuk menunjukkannya, saya mengubah sampel di atas sedikit. Harap perhatikan bahwa saya menambahkan penghitung tambahan untuk memberikan penghentian loop:
Keluaran:
Demo langsung di coliru
sumber
std::set
. Mungkin perlu untuk mempertimbangkan kasus perbatasan bahwa iterator baru dimasukkan langsung di belakang terhapus. - Ini akan dilewati setelah penyisipan dalam loop.extract
simpul, memodifikasi kunci mereka, dan mengembalikannya ke pengaturan. Akan lebih efisien, karena menghindari alokasi yang tidak perlu.std::set
. Karena Anda tidak dapat memiliki elemen yang sama dua kali, penyisipan hanya akan meninggalkan yangstd::set
tidak berubah dan Anda akan kehilangan elemen nanti. Pertimbangkan misalnya set input:{10, 20, 30}
denganadd = 10
.Sederhana hanya dengan menggantinya dengan set lain
sumber
Anda tidak dapat mengubah elemen
std::set
menurut desain. Lihathttps://en.cppreference.com/w/cpp/container/set/begin
Itu karena set diurutkan . Jika Anda bermutasi elemen dalam koleksi yang diurutkan koleksi harus diurutkan lagi, yang tentu saja mungkin, tetapi tidak dengan cara C ++.
Pilihan Anda adalah:
std::set
, modifikasi, lalu masukkan lagi. (Ini bukan ide yang baik jika Anda ingin memodifikasi setiap elemen)sumber
A
std::set
biasanya diimplementasikan sebagai pohon biner self-balancing di STL.*it
adalah nilai elemen yang digunakan untuk memesan pohon. Jika dimungkinkan untuk memodifikasinya, pesanan akan menjadi tidak valid sehingga tidak mungkin untuk melakukannya.Jika Anda ingin memperbarui elemen, maka Anda harus menemukan elemen itu di set, hapus dan masukkan nilai elemen yang diperbarui. Tetapi karena Anda harus memperbarui nilai semua elemen, maka Anda harus menghapus dan memasukkan semua elemen satu per satu.
Dimungkinkan untuk melakukannya dalam satu untuk loop yang disediakan
sub > 0
.S.erase(pos)
menghapus iterator di posisipos
dan mengembalikan posisi berikut. Jikasub > 0
, nilai yang diperbarui yang akan Anda masukkan akan datang sebelum nilai di iterator baru di pohon tetapi jikasub <= 0
, maka nilai yang diperbarui akan datang setelah nilai di iterator baru di pohon dan karenanya Anda akan berakhir di sebuah loop tak terbatas.sumber
Kesalahan cukup banyak menjelaskan masalahnya
Anggota
std::set
kontainer adalahconst
. Mengubahnya membuat pesanannya masing-masing tidak valid.Untuk mengubah elemen
std::set
, Anda harus menghapus item dan memasukkannya kembali setelah diubah.Atau, Anda bisa menggunakan
std::map
untuk mengatasi skenario ini.sumber