Saya punya vektor. Saya perlu menghapus 3 elemen terakhir di dalamnya. Dijelaskan logika ini. Program macet. Apa yang bisa menjadi kesalahannya?
vector<float>::iterator d = X.end();
for (size_t i = 1; i < 3; i++) {
if (i == 1) X.erase(d);
else X.erase(d - i);
}
d
tidak benar-benar ada. Ini adalah nilai kenari satu masa lalu yang hanya dapat digunakan untuk menemukan bagian akhirvector
. Anda tidak bisa menghapusnya. Selanjutnya, segera setelah Anda menghapus iterator, itu hilang. Anda tidak dapat menggunakannya dengan aman sesudahnya untuk apa pun, termasukd - i
.Jawaban:
Jika setidaknya ada 3 item dalam vektor, untuk menghapus 3 item terakhir adalah sederhana - cukup gunakan pop_back 3 kali:
Keluaran:
sumber
Ini adalah perilaku yang tidak ditentukan untuk meneruskan
end()
iterator ke parameter 1 yangerase()
berlebihan. Bahkan jika tidak,erase()
membatalkan iterator yang "pada dan setelah" elemen yang ditentukan, membuatd
tidak valid setelah iterasi loop pertama.std::vector
memilikierase()
kelebihan 2-parameter yang menerima serangkaian elemen untuk dihapus. Anda tidak memerlukan loop manual sama sekali:Demo Langsung
sumber
Pertama,
X.end()
tidak mengembalikan iterator ke elemen terakhir vektor, melainkan mengembalikan iterator ke elemen melewati elemen terakhir dari vektor, yang merupakan elemen yang sebenarnya tidak dimiliki vektor, itu sebabnya ketika Anda mencoba untuk hapus denganX.erase(d)
crash program.Alih-alih, asalkan vektor mengandung setidaknya 3 elemen, Anda dapat melakukan hal berikut:
Yang sebaliknya pergi ke elemen terakhir ketiga, dan menghapus setiap elemen setelah itu sampai tiba
X.end()
.EDIT: Hanya untuk memperjelas,
X.end()
adalah LegacyRandomAccessIterator yang ditentukan untuk memiliki-
operasi yang valid yang mengembalikan LegacyRandomAccessIterator lain .sumber
Definisi
end()
dari cppreference adalah:dan sedikit di bawah:
Dengan kata lain, vektor tidak memiliki elemen yang diakhiri () menunjuk ke. Dengan mendereferensi non-elemen melalui metode erase (), Anda mungkin mengubah memori yang bukan milik vektor. Karenanya hal-hal buruk dapat terjadi sejak saat itu.
Ini adalah konvensi C ++ biasa untuk menggambarkan interval sebagai [rendah, tinggi), dengan nilai "rendah" termasuk dalam interval, dan nilai "tinggi" dikeluarkan dari interval.
sumber
Anda bisa menggunakan
reverse_iterator
:Ada beberapa hal yang perlu disebutkan:
reverse_iterator rit
dimulai pada elemen terakhir darivector X
. Posisi ini disebutrbegin
.erase
membutuhkan klasikiterator
untuk bekerja dengannya. Kami mendapatkannya daririt
meneleponbase
. Tapi iterator baru itu akan menunjuk ke elemen berikutnya daririt
arah maju.rit
sebelum meneleponbase
danerase
Juga jika Anda ingin tahu lebih banyak tentang
reverse_iterator
, saya sarankan mengunjungi jawaban ini .sumber
Sebuah komentar (sekarang dihapus) dalam pertanyaan menyatakan bahwa "tidak ada - operator untuk iterator." Namun, kode berikut ini mengkompilasi dan berfungsi di keduanya
MSVC
danclang-cl
, dengan standar yang ditetapkan baikC++17
atauC++14
:Definisi yang disediakan untuk
operator-
adalah sebagai berikut (di<vector>
header):Namun, saya jelas bukan pengacara bahasa C ++, dan mungkin saja ini adalah salah satu ekstensi Microsoft yang 'berbahaya'. Saya akan sangat tertarik untuk mengetahui apakah ini bekerja pada platform / kompiler lain.
sumber
-
didefinisikan untuk tipe iterator tersebut.operator-
definisi untuk iterator, Anda bisa menggunakanstd::advance()
ataustd::prev()
sebaliknya.Pernyataan ini
memiliki perilaku yang tidak terdefinisi.
Dan pernyataan ini mencoba untuk menghapus hanya elemen sebelum elemen terakhir
karena Anda memiliki satu lingkaran dengan hanya dua iterasi
Anda perlu sesuatu seperti yang berikut ini.
Output program adalah
sumber