Saya menggunakan perpustakaan internal yang dirancang untuk meniru perpustakaan C ++ yang diusulkan , dan kadang-kadang dalam beberapa tahun terakhir saya melihat antarmuka berubah dari menggunakan std::string
ke string_view
.
Jadi saya dengan patuh mengubah kode saya, agar sesuai dengan antarmuka baru. Sayangnya, yang harus saya sampaikan adalah parameter std :: string, dan sesuatu yang merupakan nilai pengembalian std :: string. Jadi kode saya berubah dari sesuatu seperti ini:
void one_time_setup(const std::string & p1, int p2) {
api_class api;
api.setup (p1, special_number_to_string(p2));
}
untuk
void one_time_setup(const std::string & p1, int p2) {
api_class api;
const std::string p2_storage(special_number_to_string(p2));
api.setup (string_view(&p1[0], p1.size()), string_view(&p2_storage[0], p2_storage.size()));
}
Saya benar - benar tidak melihat perubahan apa yang saya beli sebagai klien API, selain lebih banyak kode (untuk kemungkinan gagal). Panggilan API kurang aman (karena API tidak lagi memiliki penyimpanan untuk parameternya), mungkin menyimpan program saya 0 bekerja (karena pemindahan optimisasi dapat dilakukan oleh kompiler sekarang), dan bahkan jika itu memang menghemat pekerjaan, itu hanya akan menjadi beberapa alokasi yang tidak dan tidak akan pernah dilakukan setelah startup atau dalam lingkaran besar di suatu tempat. Bukan untuk API ini.
Namun, pendekatan ini tampaknya mengikuti saran yang saya lihat di tempat lain, misalnya jawaban ini :
Sebagai tambahan, karena C ++ 17 Anda harus menghindari melewatkan const std :: string & yang mendukung std :: string_view:
Saya menemukan saran yang mengejutkan, karena tampaknya mengadvokasi secara universal mengganti objek yang relatif aman dengan yang kurang aman (pada dasarnya pointer dan panjang yang dimuliakan), terutama untuk keperluan optimasi.
Jadi kapan seharusnya string_view digunakan, dan kapan seharusnya tidak?
sumber
std::string_view
konstruktor secara langsung, Anda hanya harus meneruskan string ke metode yang mengambilstd::string_view
langsung dan itu akan secara otomatis dikonversi.<string>
header dan terjadi secara otomatis. Kode itu menipu dan salah.Jawaban:
std::string
(non-const, non-ref). Opsi ini memberi Anda pilihan untuk secara eksplisit bergerak dalam nilai juga jika Anda tahu bahwa itu tidak akan pernah digunakan lagi dalam konteks panggilan.std::string_view
(const, non-ref) ini karenastring_view
dapat menanganistd::string
danchar*
dengan mudah tanpa masalah dan tanpa membuat salinan. Ini harus mengganti semuaconst std::string&
parameter.Pada akhirnya Anda seharusnya tidak perlu memanggil
std::string_view
konstruktor seperti Anda.std::string
memiliki operator konversi yang menangani konversi secara otomatis.sumber
std::string_view
lebih mudah digunakan. Jika pengembang salah menggunakannya dalam situasi memiliki itu kesalahan pemrograman.std::string_view
benar-benar tidak memiliki.const, non-ref
? Parameter yang menjadi const tergantung pada penggunaan spesifik, tetapi secara umum masuk akal sebagai non-const. Dan Anda melewatkan 3. Dapat menerima irisanconst std::string_view &
di tempatconst std::string &
?A
std::string_view
membawa beberapa manfaat aconst char*
ke C ++: tidak sepertistd::string
, string_viewstd::string&
.Ini berarti string_view sering dapat menghindari salinan, tanpa harus berurusan dengan pointer mentah.
Dalam kode modern,
std::string_view
harus mengganti hampir semua penggunaanconst std::string&
parameter fungsi. Ini harus menjadi perubahan yang kompatibel dengan sumber, karenastd::string
menyatakan operator konversi untukstd::string_view
.Hanya karena tampilan string tidak membantu dalam kasus penggunaan spesifik Anda di mana Anda perlu membuat string, tidak berarti bahwa itu adalah ide yang buruk secara umum. Pustaka standar C ++ cenderung dioptimalkan untuk umum daripada untuk kenyamanan. Argumen "kurang aman" tidak berlaku, karena tidak perlu membuat sendiri tampilan string.
sumber
std::string_view
adalah tidak adanyac_str()
metode, menghasilkanstd::string
objek perantara yang tidak perlu yang perlu dibangun dan dialokasikan. Ini khususnya masalah dalam API tingkat rendah.abcdef\0
dan tampilan string yang menunjuk padacde
substring, tidak ada karakter nol setelahe
- string asli memiliki dif
sana. The standar catatan juga: “Data () dapat kembali pointer ke buffer yang tidak null-dihentikan. Oleh karena itu biasanya merupakan kesalahan untuk meneruskan data () ke fungsi yang hanya memerlukan karakter konstanta * dan mengharapkan string yang diakhiri dengan null. "Saya pikir ini sedikit salah mengerti tujuan dari ini. Meskipun ini merupakan "optimasi", Anda harus benar-benar menganggapnya sebagai melepaskan diri dari keharusan menggunakan
std::string
.Pengguna C ++ telah membuat lusinan kelas string yang berbeda. Kelas string dengan panjang tetap, kelas yang dioptimalkan SSO dengan ukuran buffer sebagai parameter templat, kelas string yang menyimpan nilai hash yang digunakan untuk membandingkannya, dll. Beberapa orang bahkan menggunakan string berbasis-SAP. Jika ada satu hal yang suka dilakukan oleh programmer C ++, ia menulis kelas string.
Dan itu mengabaikan string yang dibuat dan dimiliki oleh perpustakaan C. Naked
char*
, mungkin dengan ukuran tertentu.Jadi, jika Anda menulis pustaka, dan Anda mengambil
const std::string&
, pengguna sekarang harus mengambil string apa pun yang mereka gunakan dan menyalinnya ke astd::string
. Mungkin puluhan kali.Jika Anda ingin akses ke
std::string
antarmuka spesifik string, mengapa Anda harus menyalin string? Itu sia-sia.Alasan prinsip untuk tidak mengambil
string_view
sebagai parameter adalah:Jika tujuan akhir Anda adalah meneruskan string ke antarmuka yang mengambil string yang diakhiri NUL (
fopen
, dll).std::string
dijamin akan dihentikan NUL;string_view
bukan. Dan sangat mudah untuk membuat substring view agar non-NUL dihentikan; sub-stringing astd::string
akan menyalin substring keluar ke rentang NUL-dihentikan.Saya menulis jenis gaya string_view khusus NUL-dihentikan untuk persis skenario ini. Anda dapat melakukan sebagian besar operasi, tetapi bukan operasi yang melanggar statusnya yang diakhiri NUL (misalnya, memotong dari bagian akhir).
Masalah seumur hidup. Jika Anda benar-benar perlu menyalinnya
std::string
atau memiliki array karakter yang lebih lama dari panggilan fungsi, yang terbaik adalah menyatakan ini di muka dengan mengambil aconst std::string &
. Atau hanyastd::string
sebagai parameter nilai. Dengan begitu, jika mereka sudah memiliki string seperti itu, Anda dapat mengklaim kepemilikannya segera, dan penelepon dapat pindah ke string jika mereka tidak perlu menyimpan salinannya.sumber
string_view
adalah jenis bahasa perancis yang dapat bekerja dengan apa saja.string_view
, itu mudah.