Memadamkan Elemen daripada std::vector Semasa Membalas dengan Julat Berasaskan Untuk Gelung
Membalas pada std::vektor dan mengalih keluar elemen yang sepadan dengan keadaan tertentu boleh menjadi tugas biasa dalam pengaturcaraan. Walau bagaimanapun, sintaks berasaskan julat standard untuk gelung memberikan cabaran, kerana cuba memadamkan elemen semasa melelaran boleh membatalkan lelaran.
Masalah Memadam Dalam Rangkaian Untuk Gelung
Coretan kod berikut menunjukkan isu:
for(iterator it = begin; it != end; ++it) { if(it->somecondition() ) { erase it } }
Walaupun niatnya adalah untuk mengalih keluar elemen yang memenuhi syarat, pendekatan ini tidak betul. Apabila elemen dipadamkan, iterator menjadi tidak sah. Meneruskan lelaran dengan lelaran itu membawa kepada gelagat yang tidak ditentukan.
Penyelesaian 1: Menggunakan Regular For Loop dengan Manipulasi Iterator Eksplisit
Satu penyelesaian ialah menggunakan regular for loop dengan manipulasi iterator eksplisit:
for(iterator it = begin; it != end(container) /* !!! */;) { if (it->somecondition()) { it = vec.erase(it); // Returns the new iterator to continue from. } else { ++it; } }
Perhatikan perbezaan penting di sini: kami secara eksplisit memanggil end(container) pada setiap lelaran untuk mendapatkan lelaran akhir baharu. Ini adalah perlu kerana pemadaman elemen membatalkan lelaran asal.
Penyelesaian 2: Menggunakan std::remove_if dan padam
Alternatif yang lebih cekap ialah menggabungkan std:: remove_if dan erase():
iterator it = std::remove_if(begin, end, pred); vec.erase(it, vec.end());
std::remove_if mengalih keluar elemen yang sepadan dengan predikat yang ditentukan, manakala erase() memadamkannya. Pendekatan ini mengurangkan kerumitan masa kepada O(N) daripada O(N2) dalam penyelesaian pertama.
Penyelesaian Khusus untuk Contoh Yang Diberikan
Dalam contoh khusus yang diberikan, kod berikut boleh digunakan untuk mengalih keluar acara bermasa yang dikaitkan dengan widget tertentu:
class remove_by_caller { public: remove_by_caller(AguiWidgetBase* pWidget) : mWidget(pWidget) {} template <typename T> // for now a template bool operator()(const T& pX) const { return pX.getCaller() == mWidget; } private: AguiWidgetBase* mWidget; }; std::vector<AguiTimedEvent>::iterator it = std::remove_if(timedEvents.begin(), timedEvents.end(), remove_by_caller(widget)); timedEvents.erase(it, timedEvents.end());
Atas ialah kandungan terperinci Bagaimana untuk Memadamkan Elemen dengan Selamat daripada std::vector Semasa Lelaran dengan Range-Based For Loop?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!