Saya mencoba melakukan sesuatu seperti ini:
for ( std::list< Cursor::Enum >::reverse_iterator i = m_CursorStack.rbegin(); i != m_CursorStack.rend(); ++i )
{
if ( *i == pCursor )
{
m_CursorStack.erase( i );
break;
}
}
Namun menghapus membutuhkan iterator dan bukan iterator terbalik. apakah ada cara untuk mengubah iterator terbalik menjadi iterator biasa atau cara lain untuk menghapus elemen ini dari daftar?
i != m_CursorStack.rend()
. Sebaliknya, tulislahi = m_CursorStack.rbegin(), end = m_CursorStack.rend(); i != end;
. Yaitu, inisialisasi iterator yang dapat Anda pertahankan untuk perbandingan berulang - dengan asumsi bahwa posisi akhir tidak akan berubah sebagai efek samping dari tubuh loop Anda.std::remove
?Jawaban:
Setelah beberapa penelitian dan pengujian saya menemukan solusinya. Rupanya sesuai dengan standar [24.4.1 / 1] hubungan antara i.base () dan i adalah:
(dari artikel Dr. Dobbs ):
Jadi, Anda perlu menerapkan offset saat mendapatkan basis (). Karena itu solusinya adalah:
EDIT
Memperbarui untuk C ++ 11.
reverse_iterator
i
tidak berubah:reverse_iterator
i
canggih:Saya menemukan ini jauh lebih jelas daripada solusi saya sebelumnya. Gunakan mana pun yang Anda butuhkan.
sumber
m_CursorStack.erase( (++i).base())
(man, melakukan hal ini dengan iterator terbalik membuat kepala saya sakit ...). Juga harus dicatat bahwa artikel DDJ dimasukkan ke dalam buku "Efektif STL" Meyer.*
, tetapi kita sedang berbicara tentang elemen apa yang akan Anda tunjukkan jika Andabase
, yang merupakan satu elemen di sebelah kanan. Saya bukan penggemar--(i.base())
atau(++i).base()
solusi karena mereka bermutasi iterator. Saya lebih suka(i+1).base()
yang bekerja juga.Harap dicatat bahwa
m_CursorStack.erase( (++i).base())
mungkin ada masalah jika digunakan dalam satufor
lingkaran (lihat pertanyaan asli) karena itu mengubah nilai i. Ekspresi yang benar adalahm_CursorStack.erase((i+1).base())
sumber
iterator j = i ; ++j
, karenai+1
tidak bekerja pada iterator, tapi itu ide yang tepatm_CursorStack.erase(boost::next(i).base())
dengan Boost. atau di C ++ 11m_CursorStack.erase(std::next(i).base())
Ini memerlukan
-std=c++11
bendera (untukauto
):sumber
Lucu bahwa belum ada solusi yang benar di halaman ini. Jadi, berikut ini yang benar:
Dalam hal iterator maju solusinya lurus ke depan:
Dalam hal iterator terbalik, Anda perlu melakukan hal yang sama:
Catatan:
reverse_iterator
dari iteratorstd::list::erase
sumber
Saat menggunakan metode
reverse_iterator
'sbase()
dan mengurangi hasilnya berfungsi di sini, perlu dicatat bahwa'reverse_iterator
s tidak diberi status yang sama dengan 'iterator
s biasa . Secara umum, Anda harus memilihiterator
s biasareverse_iterator
(const_iterator
danconst_reverse_iterator
s dan s), untuk alasan yang tepat seperti ini. Lihat Jurnal Dokter Dobbs untuk pembahasan mendalam tentang mengapa.sumber
sumber
Dan di sini adalah potongan kode untuk mengubah hasil hapus kembali ke iterator terbalik untuk menghapus elemen dalam wadah saat iterasi terbalik. Agak aneh, tetapi berfungsi bahkan saat menghapus elemen pertama atau terakhir:
sumber
Jika Anda tidak perlu menghapus semuanya saat Anda melanjutkan, maka untuk menyelesaikan masalah, Anda dapat menggunakan idiom hapus-hapus:
std::remove
menukar semua item dalam wadah yang cocokpCursor
sampai akhir, dan mengembalikan iterator ke item pertama yang cocok. Kemudian, rentangerase
menggunakan akan dihapus dari pertandingan pertama, dan pergi ke akhir. Urutan elemen yang tidak cocok dipertahankan.Ini mungkin bekerja lebih cepat untuk Anda jika Anda menggunakan
std::vector
, di mana menghapus di tengah konten dapat melibatkan banyak menyalin atau memindahkan.Atau tentu saja, jawaban di atas menjelaskan penggunaan
reverse_iterator::base()
yang menarik dan layak diketahui, untuk memecahkan masalah yang dinyatakan, saya berpendapat bahwastd::remove
ini lebih cocok.sumber
Hanya ingin mengklarifikasi sesuatu: Dalam beberapa komentar di atas dan menjawab versi portable untuk erase disebut sebagai (++ i) .base (). Namun, kecuali jika saya melewatkan sesuatu, pernyataan yang benar adalah (++ ri) .base (), artinya Anda 'menambah' the reverse_iterator (bukan iterator).
Saya bertemu dengan kebutuhan untuk melakukan sesuatu yang serupa kemarin dan posting ini sangat membantu. Terimakasih semuanya.
sumber
Untuk melengkapi jawaban orang lain dan karena saya menemukan pertanyaan ini ketika mencari tentang std :: string tanpa banyak keberhasilan, ini dia tanggapan dengan penggunaan std :: string, std :: string :: erase dan std :: reverse_iterator
Masalah saya adalah menghapus nama file gambar dari string nama file lengkap. Awalnya diselesaikan dengan std :: string :: find_last_of, namun saya mencari cara alternatif dengan std :: reverse_iterator.
Ini menggunakan algoritma, iterator, dan header string.
sumber
iterator terbalik cukup sulit digunakan. Jadi hanya digunakan iterator umum. Mulai dari elemen terakhir. Ketika menemukan sesuatu untuk dihapus. hapus dan kembalikan iterator berikutnya. misal ketika menghapus elemen ke-3 akan menunjuk elemen ke-4 saat ini. dan baru ke-3. Jadi harus dikurangi 1 untuk bergerak ke kiri
sumber