std::string_view
telah berhasil mencapai C ++ 17 dan direkomendasikan untuk menggunakannya sebagai gantinya const std::string&
.
Salah satu alasannya adalah kinerja.
Dapatkah seseorang menjelaskan bagaimana tepatnya std::string_view
/ akan lebih cepat daripada const std::string&
ketika digunakan sebagai tipe parameter? (Mari kita asumsikan tidak ada salinan di callee yang dibuat)
c++
string
c++17
string-view
Patryk
sumber
sumber
std::string_view
hanyalah abstraksi dari pasangan (char * begin, char * end). Anda menggunakannya saat membuatstd::string
salinan yang tidak perlu.std::string
(string_view dapat menerima array mentah, vektor,std::basic_string<>
dengan pengalokasi non-default dll. Dll. Oh, dan string_views lainnya jelas)Jawaban:
std::string_view
lebih cepat dalam beberapa kasus.Pertama,
std::string const&
membutuhkan data dalam astd::string
, dan bukan array C mentah,char const*
dikembalikan oleh API C, yangstd::vector<char>
dihasilkan oleh beberapa mesin deserialisasi, dll. Konversi format yang dihindari menghindari menyalin byte, dan (jika string lebih panjang dari SBO¹ untukstd::string
implementasi tertentu ) menghindari alokasi memori.Tidak ada alokasi yang dilakukan dalam
string_view
kasus ini, tetapi akan ada jikafoo
mengambilstd::string const&
alih astring_view
.Alasan kedua yang sangat besar adalah bahwa ia memungkinkan bekerja dengan substring tanpa salinan. Misalkan Anda mengurai string 2 gigabyte json (!) ². Jika Anda menguraikannya
std::string
, masing-masing node parse di mana mereka menyimpan nama atau nilai dari sebuah node menyalin data asli dari string 2 gb ke node lokal.Sebagai gantinya, jika Anda menguraikannya ke
std::string_view
s, node merujuk ke data asli. Ini dapat menghemat jutaan alokasi dan membagi dua persyaratan memori selama parsing.Speedup yang bisa Anda dapatkan cukup konyol.
Ini adalah kasus yang ekstrim, tetapi kasus "dapatkan substring dan bekerja dengannya" yang lain juga dapat menghasilkan speedup yang layak
string_view
.Bagian penting dari keputusan adalah apa yang Anda hilangkan dengan menggunakan
std::string_view
. Tidak banyak, tapi itu sesuatu.Anda kehilangan terminasi nol implisit, dan hanya itu saja. Jadi jika string yang sama akan diteruskan ke 3 fungsi yang semuanya membutuhkan terminator nol, konversi ke
std::string
sekali mungkin bijaksana. Jadi, jika kode Anda diketahui membutuhkan terminator nol, dan Anda tidak mengharapkan string diumpankan dari buffer bersumber gaya C atau sejenisnya, mungkin ambil astd::string const&
. Kalau tidak ambil astd::string_view
.Jika
std::string_view
memiliki bendera yang menyatakan apakah itu nol diakhiri (atau sesuatu yang lebih menarik) itu akan menghapus bahkan alasan terakhir untuk menggunakan astd::string const&
.Ada kasus di mana mengambil
std::string
dengan tidakconst&
optimal lebih dari astd::string_view
. Jika Anda perlu memiliki salinan string tanpa batas waktu setelah panggilan, mengambil menurut nilai lebih efisien. Anda akan berada dalam case SBO (dan tidak ada alokasi, hanya beberapa salinan karakter untuk menduplikasinya), atau Anda akan dapat memindahkan buffer yang dialokasikan heap ke lokalstd::string
. Memiliki dua kelebihanstd::string&&
danstd::string_view
mungkin lebih cepat, tetapi hanya sedikit, dan itu akan menyebabkan kode gembung sederhana (yang dapat dikenakan biaya semua kenaikan kecepatan).¹ Optimasi Penyangga Kecil
² Kasus penggunaan aktual.
sumber
Salah satu cara string_view meningkatkan kinerja adalah bahwa ia memungkinkan untuk menghapus awalan dan akhiran dengan mudah. Di bawah tenda, string_view hanya dapat menambahkan ukuran awalan ke pointer ke beberapa buffer string, atau kurangi ukuran akhiran dari penghitung byte, ini biasanya cepat. std :: string di sisi lain harus menyalin byte-nya ketika Anda melakukan sesuatu seperti substr (cara ini Anda mendapatkan string baru yang memiliki buffer, tetapi dalam banyak kasus Anda hanya ingin mendapatkan bagian dari string asli tanpa menyalin). Contoh:
Dengan std :: string_view:
Memperbarui:
Saya menulis patokan yang sangat sederhana untuk menambahkan beberapa bilangan real. Saya menggunakan pustaka tolok ukur google yang mengagumkan . Fungsi yang dibandingan adalah:
Hasil
(x86_64 linux, gcc 6.2, "
-O3 -DNDEBUG
"):sumber
Ada 2 alasan utama:
string_view
adalah irisan dalam buffer yang ada, tidak memerlukan alokasi memoristring_view
dilewatkan oleh nilai, bukan oleh referensiKeuntungan memiliki sepotong adalah beberapa:
char const*
atauchar[]
tanpa mengalokasikan buffer baruKinerja yang lebih baik dan lebih konsisten di seluruh.
Melewati dengan nilai juga memiliki kelebihan dibandingkan melewatinya dengan referensi, karena aliasing.
Khususnya, ketika Anda memiliki
std::string const&
parameter, tidak ada jaminan bahwa string referensi tidak akan dimodifikasi. Akibatnya, kompiler harus mengambil kembali konten string setelah setiap panggilan menjadi metode buram (pointer ke data, panjang, ...).Di sisi lain, ketika melewati
string_view
nilai, kompiler secara statis dapat menentukan bahwa tidak ada kode lain yang dapat memodifikasi panjang dan data pointer sekarang di stack (atau dalam register). Sebagai hasilnya, itu bisa "cache" mereka di panggilan fungsi.sumber
Satu hal yang dapat dilakukan adalah menghindari membangun
std::string
objek jika ada konversi implisit dari string yang diakhiri dengan nol:sumber
const std::string str{"goodbye!"}; foo(str);
mungkin tidak akan ada yang lebih cepat dengan string_view daripada dengan string &string_view
akan lambat karena harus menyalin dua pointer sebagai lawan satu pointerconst string&
?std::string_view
pada dasarnya hanyalah sebuah pembungkus di sekitar aconst char*
. Dan passingconst char*
berarti bahwa akan ada satu pointer kurang dalam sistem dibandingkan dengan passingconst string*
(atauconst string&
), karenastring*
menyiratkan sesuatu seperti:Jelas untuk tujuan melewati argumen const pointer pertama tidak berguna.
ps Satu perbedaan mendasar antara
std::string_view
danconst char*
, bagaimanapun, adalah bahwa string_view tidak diharuskan untuk diakhiri nol (mereka memiliki ukuran bawaan), dan ini memungkinkan penyambungan acak di tempat dari string yang lebih panjang.sumber
std::string_view
Ini hanya mewahconst char*
, titik. GCC mengimplementasikannya seperti ini:class basic_string_view {const _CharT* _M_str; size_t _M_len;}
std::string const*
. Dan diagram itu tidak bisa dipahami. @ n.caillou: Komentar Anda sendiri sudah lebih akurat daripada jawabannya. Itu membuatstring_view
lebih dari "mewahchar const*
" - itu sangat jelas.std::string const*
danstd::string const&
sama, bukan?