Saya menemukan perilaku std::string::find
tidak konsisten dengan wadah standar C ++.
Misalnya
std::map<int, int> myMap = {{1, 2}};
auto it = myMap.find(10); // it == myMap.end()
Tapi untuk sebuah string,
std::string myStr = "hello";
auto it = myStr.find('!'); // it == std::string::npos
Kenapa bukan yang gagal myStr.find('!')
kembali myStr.end()
saja std::string::npos
?
Karena std::string
agak istimewa jika dibandingkan dengan wadah lain, saya bertanya-tanya apakah ada alasan nyata di balik ini. (Anehnya, saya tidak dapat menemukan orang yang mempertanyakan hal ini di mana pun).
c++
stdstring
c++-standard-library
Sumudu
sumber
sumber
std::string
internal terdiri dari karakter yang merupakan elemen murah (dalam hal memori). Dan, lebih jauh lagi, karakter adalah satu-satunya tipe yangstd::string
bisa mengandung. Di sisi lain,std::map
terdiri dari elemen yang lebih kompleks. Juga, spesifikasistd::map::find
mengatakan bahwa ia seharusnya menemukan elemen, dan spesifikasistd::string::find
mengatakan bahwa tugasnya adalah menemukan posisi.Jawaban:
Untuk memulainya,
std::string
antarmuka dikenal membengkak dan tidak konsisten, lihat Herb Sutter's Gotw84 tentang topik ini. Namun demikian, ada alasan di balikstd::string::find
kembali indeks:std::string::substr
. Fungsi kenyamanan anggota ini beroperasi pada indeks, misalnyaAnda dapat mengimplementasikan
substr
sedemikian rupa sehingga menerima iterator ke dalam string, tetapi kemudian kita tidak perlu menunggu lama untuk keluhan keras yangstd::string
tidak dapat digunakan dan berlawanan dengan intuisi. Jadi mengingat bahwastd::string::substr
menerima indeks, bagaimana Anda menemukan indeks kemunculan pertama'd'
dalam string input di atas untuk mencetak semuanya mulai dari substring ini?Ini mungkin juga bukan yang Anda inginkan. Karenanya kita dapat membiarkan
std::string::find
mengembalikan indeks, dan di sini kita:Jika Anda ingin bekerja dengan iterator, gunakan
<algorithm>
. Mereka memungkinkan Anda untuk di atas sebagaisumber
std::string::find
masih bisa mengembalikansize()
, alih-alihnpos
, mempertahankan kompatibilitas dengansubstr
, sambil juga menghindari beberapa bilah ekstra.std::string::substr
sudah mencakup kasus "mulai di sini sampai akhir" dengan parameter default untuk indeks kedua (npos
). Saya kira kembalisize()
juga akan membingungkan dan memiliki penjaga seperti itunpos
mungkin merupakan pilihan yang lebih baik?std::string::find
mengembalikan iterator,std::string::substr
mungkin juga akan menerima iterator untuk posisi awal. Contoh Anda dengan find akan terlihat sama dalam kedua kasus di dunia alternatif ini.std::string::substr
dengan argumen iterator membuka pintu untuk satu kasus UB lebih lanjut (selain skenario masa lalu-akhir yang bisa sama baiknya dengan indeks atau iterator): melewati iterator yang merujuk ke string lain.Ini karena
std::string
memiliki dua antarmuka:std::string
spesifik Indeks antarmuka berbasisstd::string::find
adalah bagian dari antarmuka berbasis indeks , dan karenanya mengembalikan indeks.Gunakan
std::find
untuk menggunakan antarmuka berbasis iterator umum.Gunakan
std::vector<char>
jika Anda tidak ingin antarmuka berbasis indeks (jangan lakukan ini).sumber