Rumah > pembangunan bahagian belakang > C++ > Bagaimana untuk Memadamkan Elemen dengan Selamat daripada std::vector Semasa Lelaran dengan Range-Based For Loop?

Bagaimana untuk Memadamkan Elemen dengan Selamat daripada std::vector Semasa Lelaran dengan Range-Based For Loop?

Susan Sarandon
Lepaskan: 2024-11-03 17:09:03
asal
935 orang telah melayarinya

How to Safely Erase Elements from a std::vector During Iteration with a Range-Based For Loop?

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
    }

}
Salin selepas log masuk

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;
    }
}
Salin selepas log masuk

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());
Salin selepas log masuk

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&amp; 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());
Salin selepas log masuk

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!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan