Saya punya kode yang terlihat seperti ini:
for (std::list<item*>::iterator i=items.begin();i!=items.end();i++)
{
bool isActive = (*i)->update();
//if (!isActive)
// items.remove(*i);
//else
other_code_involving(*i);
}
items.remove_if(CheckItemNotActive);
Saya ingin menghapus item yang tidak aktif segera setelah memperbaruinya, inorder untuk menghindari berjalan daftar lagi. Tetapi jika saya menambahkan baris komentar, saya mendapatkan kesalahan ketika saya sampai ke i++
: "Daftar iterator not incrementable". Saya mencoba beberapa alternatif yang tidak bertambah dalam pernyataan untuk, tapi saya tidak bisa mendapatkan apa pun untuk bekerja.
Apa cara terbaik untuk menghapus item saat Anda berjalan di std :: list?
Jawaban:
Anda harus menambahkan iterator terlebih dahulu (dengan i ++) dan kemudian menghapus elemen sebelumnya (misalnya, dengan menggunakan nilai yang dikembalikan dari i ++). Anda dapat mengubah kode menjadi loop sementara seperti:
sumber
i = items.erase(i)
lebih aman, karena setara dengan daftar, tetapi akan tetap berfungsi jika seseorang mengubah wadah ke vektor. Dengan vektor, hapus () memindahkan semuanya ke kiri untuk mengisi lubang. Jika Anda mencoba untuk menghapus item terakhir dengan kode yang menambah iterator setelah dihapus, ujungnya bergerak ke kiri, dan iterator bergerak ke kanan - melewati ujungnya. Dan kemudian Anda jatuh.Anda ingin melakukan:
Itu akan benar memperbarui iterator untuk menunjuk ke lokasi setelah iterator Anda dihapus.
sumber
i==items.begin()
?i= items.erase(i);
. Ini adalah bentuk kanonik dan sudah mengurus semua perincian itu.Anda perlu melakukan kombinasi jawaban Kristo dan MSN:
Tentu saja, hal yang paling efisien dan SuperCool® STL akan seperti ini:
sumber
Gunakan algoritma std :: remove_if.
Edit: Bekerja dengan koleksi harus seperti: 1. menyiapkan koleksi. 2. proses pengumpulan.
Hidup akan lebih mudah jika Anda tidak akan mencampur langkah-langkah ini.
sumber
Berikut ini contoh menggunakan
for
loop yang mengulang daftar dan menambah atau memvalidasi ulang iterator jika ada item yang dihapus selama traversal daftar.sumber
Alternatif untuk versi loop ke jawaban Kristo.
Anda kehilangan beberapa efisiensi, Anda mundur dan maju lagi ketika menghapus tetapi dengan imbalan kenaikan iterator tambahan Anda dapat memiliki iterator dideklarasikan dalam lingkup loop dan kode tampak sedikit lebih bersih. Apa yang harus dipilih tergantung pada prioritas saat ini.
Jawabannya benar-benar kehabisan waktu, saya tahu ...
sumber
iterator cannot be decremented
Theerase
Metode membutuhkanrandom access iterator
. Beberapa implementasi pengumpulan menyediakan suatuforward only iterator
yang menyebabkan penegasan.Saya sudah simpulkan, berikut adalah tiga metode dengan contoh:
1. menggunakan
while
loop2. menggunakan
remove_if
funtion anggota dalam daftar:3. menggunakan
std::remove_if
kombinasi funtion denganerase
fungsi anggota:4. menggunakan
for
loop, harus perhatikan pembaruan iterator:sumber
Penghapusan hanya membatalkan iterator yang menunjuk ke elemen yang dihapus.
Jadi dalam hal ini setelah menghapus * i, saya tidak valid dan Anda tidak dapat melakukan peningkatan padanya.
Yang bisa Anda lakukan adalah pertama-tama menyimpan iterator elemen yang akan dihapus, kemudian menambahkan iterator dan kemudian menghapus yang disimpan.
sumber
Jika Anda berpikir tentang
std::list
antrian seperti, maka Anda dapat mengeluarkan dan mengirimkan semua item yang ingin Anda simpan, tetapi hanya dequeue (dan bukan enqueue) item yang ingin Anda hapus. Berikut adalah contoh di mana saya ingin menghapus 5 dari daftar yang berisi angka 1-10 ...myList
sekarang hanya akan memiliki angka 1-4 dan 6-10.sumber
Iterasi mundur menghindari efek menghapus elemen pada elemen yang tersisa untuk dilalui:
PS: lihat ini , misalnya, tentang iterasi mundur.
PS2: Saya tidak diuji secara menyeluruh jika menangani elemen yang dihapus dengan baik di ujungnya.
sumber
avoids the effect of erasing an element on the remaining elements
untuk daftar, mungkin ya. Untuk vektor mungkin tidak. Itu bukan sesuatu yang dijamin pada koleksi sewenang-wenang. Misalnya, peta dapat memutuskan untuk menyeimbangkan dirinya sendiri.Kamu bisa menulis
Anda dapat menulis kode setara dengan
std::list::remove_if
, yang kurang verbose dan lebih eksplisitThe
std::vector::erase
std::remove_if
idiom harus digunakan bila item adalah vektor bukan daftar untuk menjaga compexity di O (n) - atau jika Anda menulis kode generik dan item mungkin wadah dengan tidak ada cara yang efektif untuk menghapus item tunggal (seperti vektor)sumber
Saya pikir Anda memiliki bug di sana, saya kode dengan cara ini:
sumber