Mengapa Rust memiliki String
dan str
? Apa perbedaan antara String
dan str
? Kapan seseorang menggunakan dan String
bukannya str
sebaliknya? Apakah salah satu dari mereka mulai ditinggalkan?
String
adalah tipe string tumpukan dinamis, seperti Vec
: gunakan ketika Anda perlu memiliki atau memodifikasi data string Anda.
str
adalah 1 urutan UTF-8 byte panjang dinamis yang tidak dapat diubah di suatu tempat di memori. Karena ukurannya tidak diketahui, orang hanya bisa menanganinya di belakang pointer. Ini berarti bahwa str
paling umum 2 muncul sebagai &str
: referensi ke beberapa data UTF-8, biasanya disebut "string slice" atau hanya "slice". Sepotong hanyalah pandangan ke beberapa data, dan data itu bisa di mana saja, misalnya
"foo"
adalah a &'static str
. Data di-hardcode ke dalam executable dan dimuat ke dalam memori ketika program berjalan.String
: String
dereferences ke &str
tampilan dari String
data yang 's.Pada stack : misalnya yang berikut ini membuat array byte yang dialokasikan stack, dan kemudian mendapatkan tampilan data itu sebagai&str
:
use std::str;
let x: &[u8] = &[b'a', b'b', b'c'];
let stack_str: &str = str::from_utf8(x).unwrap();
Singkatnya, gunakan String
jika Anda membutuhkan data string yang dimiliki (seperti meneruskan string ke utas lain, atau membangunnya saat runtime), dan gunakan &str
jika Anda hanya memerlukan tampilan string.
Ini identik dengan hubungan antara vektor Vec<T>
dan irisan &[T]
, dan mirip dengan hubungan antara nilai- T
dan referensi- &T
untuk tipe umum.
1 A str
adalah panjang tetap; Anda tidak dapat menulis byte di luar akhirnya, atau meninggalkan byte yang tidak valid. Karena UTF-8 adalah pengodean lebar variabel, ini secara efektif memaksa semua str
s tidak berubah dalam banyak kasus. Secara umum, mutasi memerlukan penulisan byte lebih banyak atau lebih sedikit daripada sebelumnya (misalnya mengganti a
(1 byte) dengan ä
(2+ byte) akan membutuhkan ruang lebih banyak di dalam str
). Ada metode khusus yang dapat memodifikasi &str
di tempat, kebanyakan yang hanya menangani karakter ASCII, seperti make_ascii_uppercase
.
2 Jenis berukuran dinamis memungkinkan hal-hal seperti Rc<str>
untuk urutan referensi dihitung UTF-8 byte sejak Rust 1.2. Karat 1.21 memungkinkan dengan mudah membuat jenis ini.
&str
terdiri dari dua komponen: pointer ke beberapa byte, dan panjang a."[u8; N]
,.Rc<str>
danArc<str>
sekarang dapat digunakan melalui perpustakaan standar.Saya memiliki latar belakang C ++ dan saya merasa sangat berguna untuk memikirkan
String
dan&str
dalam istilah C ++:String
sepertistd::string
; ia memiliki memori dan melakukan pekerjaan kotor mengelola memori.&str
sepertichar*
(tetapi sedikit lebih canggih); itu mengarahkan kita ke awal chunk dengan cara yang sama Anda bisa mendapatkan pointer ke isistd::string
.Apakah salah satu dari mereka akan menghilang? Saya kira tidak. Mereka melayani dua tujuan:
String
menjaga buffer dan sangat praktis untuk digunakan.&str
ringan dan harus digunakan untuk "melihat" string. Anda dapat mencari, membagi, mem-parsing, dan bahkan mengganti potongan tanpa perlu mengalokasikan memori baru.&str
dapat melihat ke dalamString
karena dapat menunjuk ke beberapa string literal. Kode berikut perlu menyalin string literal ke dalamString
memori yang dikelola:Kode berikut memungkinkan Anda menggunakan literal itu sendiri tanpa salinan (hanya baca saja)
sumber
str
, hanya digunakan sebagai&str
, adalah slice string, referensi ke array byte UTF-8.String
adalah apa yang dulunya adalah~str
, sebuah array byte UTF-8 yang dapat ditanam, dimiliki.sumber
~str
adalah sekarangBox<str>
~str
sudah bisa ditanami sementaraBox<str>
tidak bisa ditanami. (Itu~str
dan~[T]
dapat ditumbuhkan secara ajaib, tidak seperti objek lainnya~
, persis mengapaString
danVec<T>
diperkenalkan, sehingga aturannya mudah dan konsisten.)Mereka sebenarnya sangat berbeda. Pertama, a
str
tidak lain adalah level level; itu hanya dapat dipertimbangkan pada tingkat tipe karena itu disebut tipe ukuran dinamis (DST). Ukuranstr
memakan waktu tidak dapat diketahui pada waktu kompilasi dan tergantung pada informasi runtime - itu tidak dapat disimpan dalam variabel karena kompiler perlu tahu pada waktu kompilasi berapa ukuran masing-masing variabel. Astr
secara konseptual hanyalah deretanu8
byte dengan jaminan bahwa itu membentuk UTF-8 yang valid. Berapa besar barisnya? Tidak ada yang tahu sampai runtime karena itu tidak dapat disimpan dalam variabel.Hal yang menarik adalah bahwa
&str
atau pointer lain untukstr
sepertiBox<str>
tidak eksis pada saat runtime. Ini disebut "penunjuk gemuk"; itu adalah penunjuk dengan informasi tambahan (dalam hal ini ukuran benda yang ditunjuknya) sehingga dua kali lebih besar. Bahkan, a&str
cukup dekat denganString
(tetapi tidak ke a&String
). A&str
adalah dua kata; satu pointer ke byte pertama daristr
dan nomor lain yang menggambarkan berapa byte panjangnyastr
.Bertentangan dengan apa yang dikatakan, a
str
tidak perlu abadi. Jika Anda bisa mendapatkan&mut str
sebagai penunjuk eksklusif kestr
, Anda dapat bermutasi dan semua fungsi aman yang bermutasi menjamin bahwa batasan UTF-8 ditegakkan karena jika itu dilanggar maka kami memiliki perilaku yang tidak ditentukan karena perpustakaan menganggap batasan ini adalah benar dan tidak memeriksa untuk itu.Jadi, apa itu
String
? Itu tiga kata; keduanya sama seperti untuk&str
tetapi menambahkan kata ketiga yang merupakan kapasitasstr
buffer di heap, selalu di heap (astr
tidak harus di heap) itu dikelola sebelum diisi dan harus mengalokasikan kembali. yangString
pada dasarnya memiliki sebuahstr
seperti yang mereka katakan; itu mengontrolnya dan dapat mengubah ukurannya dan mengalokasikannya kembali jika dianggap cocok. JadiString
seperti yang dikatakan lebih dekat ke&str
daripada kestr
.Hal lain adalah
Box<str>
; ini juga memilikistr
dan representasi runtime-nya sama dengan&str
tetapi ia juga memiliki yangstr
tidak seperti&str
itu tetapi tidak dapat mengubah ukurannya karena tidak mengetahui kapasitasnya sehingga pada dasarnya aBox<str>
dapat dilihat sebagai panjang tetapString
yang tidak dapat diubah ukurannya (Anda dapat selalu ubah menjadiString
jika Anda ingin mengubah ukurannya).Hubungan yang sangat mirip ada antara
[T]
danVec<T>
kecuali tidak ada batasan UTF-8 dan dapat menampung semua jenis yang ukurannya tidak dinamis.Penggunaan
str
pada level tipe sebagian besar untuk membuat abstraksi generik dengan&str
; itu ada pada tingkat tipe untuk dapat dengan mudah menulis ciri. Secara teoristr
sebagai tipe hal tidak perlu ada dan hanya&str
tetapi itu berarti banyak kode tambahan harus ditulis yang sekarang bisa menjadi generik.&str
sangat berguna untuk dapat memiliki beberapa substring yang berbedaString
tanpa harus menyalin; sebagai kata seorangString
memiliki yangstr
pada tumpukan itu berhasil dan jika Anda hanya bisa membuat substring dariString
dengan baruString
itu harus disalin karena segala sesuatu di Rust hanya dapat memiliki satu pemilik tunggal untuk menangani keamanan memori. Jadi misalnya Anda dapat mengiris string:Kami memiliki dua substring berbeda
str
dari string yang sama.string
adalah salah satu yang memilikistr
buffer penuh aktual pada heap dan&str
substring hanya pointer gemuk ke buffer di heap.sumber
std::String
hanyalah sebuah vektor dariu8
. Anda dapat menemukan definisinya dalam kode sumber . Ini tumpukan dialokasikan dan ditumbuhkan.str
adalah tipe primitif, juga disebut string slice . Irisan string memiliki ukuran tetap. String literal sepertilet test = "hello world"
memiliki&'static str
tipe.test
adalah referensi untuk string yang dialokasikan secara statis ini.&str
tidak dapat dimodifikasi, misalnya,str
memang memiliki irisan yang bisa berubah&mut str
, misalnya:pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str)
Tetapi perubahan kecil ke UTF-8 dapat mengubah panjang byte-nya, dan irisan tidak dapat realokasi referensi.
sumber
Dengan kata mudah,
String
apakah tipe data disimpan di heap (sama sepertiVec
), dan Anda memiliki akses ke lokasi itu.&str
adalah tipe slice. Itu berarti itu hanya referensi ke suatu tempat yang sudah adaString
di tumpukan.&str
tidak melakukan alokasi apa pun pada saat runtime. Jadi, untuk alasan memori, Anda dapat menggunakan&str
lebih dari ituString
. Namun, perlu diingat bahwa ketika menggunakan&str
Anda mungkin harus berurusan dengan kehidupan eksplisit.sumber
str
adalahview
dari yang sudah adaString
di tumpukan.Untuk orang-orang C # dan Java:
String
===StringBuilder
&str
String === (tidak berubah) dari RustSaya suka menganggap
&str
sebagai tampilan pada string, seperti string yang diinternir di Java / C # di mana Anda tidak dapat mengubahnya, hanya membuat yang baru.sumber
Berikut ini penjelasan yang cepat dan mudah.
String
- Struktur data yang dialokasikan dan dapat ditimbun milik sendiri. Itu bisa dipaksa untuk&str
.str
- adalah (sekarang, ketika Rust berevolusi) string yang dapat berubah, tetap-panjang yang hidup di heap atau dalam biner. Anda hanya dapat berinteraksi denganstr
sebagai tipe pinjaman melalui tampilan slice string, seperti&str
.Pertimbangan penggunaan:
Lebih suka
String
jika Anda ingin memiliki atau bermutasi string - seperti meneruskan string ke utas lainnya, dll.Lebih suka
&str
jika Anda ingin memiliki tampilan string hanya-baca.sumber