Itu sepertinya tidak mungkin atau diinginkan. 'staticmasa hidup akan menyiratkan bahwa string tidak pernah dibatalkan alokasinya, yaitu kebocoran memori. Mengapa Anda membutuhkan, &'static strbukan &'a struntuk beberapa yang sesuai 'a?
3
Bagaimana rasanya mengubahnya menjadi &'a str itu?
Christoph
Melalui as_slice. Akan lebih mudah membantu jika Anda menjelaskan masalah konkret apa yang ingin Anda selesaikan dan masalah apa yang Anda hadapi saat melakukannya.
Perhatikan juga SendStr, tipe yang merupakan string yang dimiliki atau string statis.
Chris Morgan
Jawaban:
135
Diperbarui untuk Rust 1.0
Anda tidak dapat memperoleh &'static strdari Stringkarena Strings tidak mungkin hidup untuk seluruh kehidupan dari program Anda, dan bahwa ini apa &'staticberarti seumur hidup. Anda hanya bisa mendapatkan potongan yang diparameterisasi menurut Stringmasa hidupnya.
Untuk beralih dari a Stringke slice, &'a strAnda dapat menggunakan sintaks slicing:
let s: String = "abcdefg".to_owned();
let s_slice: &str = &s[..]; // take a full slice of the string
Atau, Anda dapat menggunakan fakta yang Stringmengimplementasikan Deref<Target=str>dan melakukan peminjaman kembali secara eksplisit:
let s_slice: &str = &*s; // s : String // *s : str (via Deref<Target=str>)// &*s: &str
Bahkan ada cara lain yang memungkinkan sintaks yang lebih ringkas tetapi hanya dapat digunakan jika kompiler dapat menentukan tipe target yang diinginkan (misalnya dalam argumen fungsi atau binding variabel yang diketik secara eksplisit). Ini disebut paksaan deref dan memungkinkan menggunakan &operator saja , dan kompilator akan secara otomatis memasukkan jumlah yang sesuai *berdasarkan konteks:
let s_slice: &str = &s; // okayfntake_name(name: &str) { ... }
take_name(&s); // okay as welllet not_correct = &s; // this will give &String, not &str,// because the compiler does not know// that you want a &str
Perhatikan bahwa pola ini tidak unik untuk String/ &str- Anda dapat menggunakannya dengan setiap pasangan tipe yang dihubungkan Deref, misalnya, dengan CString/ CStrdan OsString/ OsStrdari std::ffimodul atau PathBuf/ Pathdari std::pathmodul.
Di Rust 1.10 alih-alih let s_slice: &str = &s[..];Anda cukup melakukan ini:let s_slice: &str = s.as_str();
Shnatsel
3
Kadang-kadang, string asli tidak cukup hidup, seperti di blok pertandingan {...}. Itu akan menyebabkan a 's' does not live long enough error.
Dereckson
42
Anda dapat melakukannya, tetapi ini melibatkan kebocoran memori fileString . Ini bukanlah sesuatu yang harus Anda lakukan dengan mudah. Dengan membocorkan memori tersebut String, kami menjamin bahwa memori tersebut tidak akan pernah bisa dibebaskan (demikian pula kebocorannya). Oleh karena itu, setiap referensi ke objek dalam dapat diartikan sebagai memiliki masa 'statichidup.
Stringmembuat jaminan, bahwa selama objek tersebut belum dijatuhkan, memori tetap hidup. Karena mem::forgetjaminan bahwa objek tidak akan pernah dijatuhkan, kami dijamin bahwa referensi ke konten strtidak akan pernah valid. Jadi kami dapat menegaskan bahwa ini adalah 'staticreferensi
oli_obk
1
Ini sangat membantu untuk aplikasi Rust saya, yang diperlukan untuk memaksa sebuah Stringke &'static strsehingga token dibuat dari aslinya Stringakan tersedia di semua thread. Tanpa ini, kompilator Rust akan mengeluh bahwa Stringmasa pakai saya berakhir pada akhir fungsi utama, yang tidak cukup baik karena tidak memiliki 'staticjaminan.
mmstick
1
@mmstick: solusi yang lebih baik dalam hal ini adalah menggunakan crossbeamdan
cakupan
3
@mmstick: jika Anda meletakkan seluruh aplikasi Anda ke dalam lingkup crossbeam dan membuat string di luar lingkup, Anda akan mendapatkan itu.
oli_obk
1
Jawaban ini bagus! Keduanya memberi tahu saya cara dengan licik membuat potongan string statis dan meyakinkan saya untuk tidak melakukannya! Saya memilih untuk merefaktor aplikasi saya agar tidak menggunakan potongan string statis di banyak tempat.
Paul Chernoch
24
Pada Rust versi 1,26, adalah mungkin untuk mengkonversi Stringke &'static strtanpa menggunakan unsafekode:
Ini mengubah Stringcontoh menjadi sebuah kotakstr dan segera membocorkannya. Ini membebaskan semua kapasitas berlebih yang mungkin ditempati string saat ini.
Perhatikan bahwa hampir selalu ada solusi yang lebih disukai daripada objek bocor, misalnya menggunakan crossbeampeti jika Anda ingin berbagi status antar utas.
TL; DR: Anda bisa mendapatkan a &'static strdari Stringyang memiliki file'static seumur hidup.
Meskipun jawaban lain benar dan paling berguna, ada kasus tepi (tidak terlalu berguna), di mana Anda memang dapat mengonversi a Stringke a&'static str :
Umur referensi harus selalu lebih pendek atau sama dengan umur objek yang direferensikan. Yaitu objek yang direferensikan harus hidup lebih lama (atau sama panjang) dari referensi. Karena 'staticberarti seluruh masa program, masa hidup yang lebih lama tidak ada. Tapi masa hidup yang sama sudah cukup. Jadi, jika Stringseumur hidup 'static, Anda bisa mendapatkan file&'static str referensi darinya.
Membuat statictipe Stringsecara teoritis menjadi mungkin dengan Rust 1.31 ketika const fnfitur itu dirilis. Sayangnya, satu-satunya fungsi const yang mengembalikan a StringisString::new() saat, dan itu masih di belakang gerbang fitur (sehingga Rust malam diperlukan untuk saat ini).
Jadi kode berikut melakukan konversi yang diinginkan (menggunakan nightly) ... dan sebenarnya tidak memiliki penggunaan praktis kecuali untuk kelengkapan menunjukkan bahwa itu mungkin dalam kasus tepi ini.
'static
masa hidup akan menyiratkan bahwa string tidak pernah dibatalkan alokasinya, yaitu kebocoran memori. Mengapa Anda membutuhkan,&'static str
bukan&'a str
untuk beberapa yang sesuai'a
?&'a str
itu?as_slice
. Akan lebih mudah membantu jika Anda menjelaskan masalah konkret apa yang ingin Anda selesaikan dan masalah apa yang Anda hadapi saat melakukannya.SendStr
, tipe yang merupakan string yang dimiliki atau string statis.Jawaban:
Diperbarui untuk Rust 1.0
Anda tidak dapat memperoleh
&'static str
dariString
karenaString
s tidak mungkin hidup untuk seluruh kehidupan dari program Anda, dan bahwa ini apa&'static
berarti seumur hidup. Anda hanya bisa mendapatkan potongan yang diparameterisasi menurutString
masa hidupnya.Untuk beralih dari a
String
ke slice,&'a str
Anda dapat menggunakan sintaks slicing:let s: String = "abcdefg".to_owned(); let s_slice: &str = &s[..]; // take a full slice of the string
Atau, Anda dapat menggunakan fakta yang
String
mengimplementasikanDeref<Target=str>
dan melakukan peminjaman kembali secara eksplisit:let s_slice: &str = &*s; // s : String // *s : str (via Deref<Target=str>) // &*s: &str
Bahkan ada cara lain yang memungkinkan sintaks yang lebih ringkas tetapi hanya dapat digunakan jika kompiler dapat menentukan tipe target yang diinginkan (misalnya dalam argumen fungsi atau binding variabel yang diketik secara eksplisit). Ini disebut paksaan deref dan memungkinkan menggunakan
&
operator saja , dan kompilator akan secara otomatis memasukkan jumlah yang sesuai*
berdasarkan konteks:let s_slice: &str = &s; // okay fn take_name(name: &str) { ... } take_name(&s); // okay as well let not_correct = &s; // this will give &String, not &str, // because the compiler does not know // that you want a &str
Perhatikan bahwa pola ini tidak unik untuk
String
/&str
- Anda dapat menggunakannya dengan setiap pasangan tipe yang dihubungkanDeref
, misalnya, denganCString
/CStr
danOsString
/OsStr
daristd::ffi
modul atauPathBuf
/Path
daristd::path
modul.sumber
let s_slice: &str = &s[..];
Anda cukup melakukan ini:let s_slice: &str = s.as_str();
's' does not live long enough error
.Anda dapat melakukannya, tetapi ini melibatkan kebocoran memori file
String
. Ini bukanlah sesuatu yang harus Anda lakukan dengan mudah. Dengan membocorkan memori tersebutString
, kami menjamin bahwa memori tersebut tidak akan pernah bisa dibebaskan (demikian pula kebocorannya). Oleh karena itu, setiap referensi ke objek dalam dapat diartikan sebagai memiliki masa'static
hidup.fn string_to_static_str(s: String) -> &'static str { Box::leak(s.into_boxed_str()) } fn main() { let mut s = String::new(); std::io::stdin().read_line(&mut s).unwrap(); let s: &'static str = string_to_static_str(s); }
sumber
String
membuat jaminan, bahwa selama objek tersebut belum dijatuhkan, memori tetap hidup. Karenamem::forget
jaminan bahwa objek tidak akan pernah dijatuhkan, kami dijamin bahwa referensi ke kontenstr
tidak akan pernah valid. Jadi kami dapat menegaskan bahwa ini adalah'static
referensiString
ke&'static str
sehingga token dibuat dari aslinyaString
akan tersedia di semua thread. Tanpa ini, kompilator Rust akan mengeluh bahwaString
masa pakai saya berakhir pada akhir fungsi utama, yang tidak cukup baik karena tidak memiliki'static
jaminan.crossbeam
danPada Rust versi 1,26, adalah mungkin untuk mengkonversi
String
ke&'static str
tanpa menggunakanunsafe
kode:fn string_to_static_str(s: String) -> &'static str { Box::leak(s.into_boxed_str()) }
Ini mengubah
String
contoh menjadi sebuah kotakstr
dan segera membocorkannya. Ini membebaskan semua kapasitas berlebih yang mungkin ditempati string saat ini.Perhatikan bahwa hampir selalu ada solusi yang lebih disukai daripada objek bocor, misalnya menggunakan
crossbeam
peti jika Anda ingin berbagi status antar utas.sumber
TL; DR: Anda bisa mendapatkan a
&'static str
dariString
yang memiliki file'static
seumur hidup.Meskipun jawaban lain benar dan paling berguna, ada kasus tepi (tidak terlalu berguna), di mana Anda memang dapat mengonversi a
String
ke a&'static str
:Umur referensi harus selalu lebih pendek atau sama dengan umur objek yang direferensikan. Yaitu objek yang direferensikan harus hidup lebih lama (atau sama panjang) dari referensi. Karena
'static
berarti seluruh masa program, masa hidup yang lebih lama tidak ada. Tapi masa hidup yang sama sudah cukup. Jadi, jikaString
seumur hidup'static
, Anda bisa mendapatkan file&'static str
referensi darinya.Membuat
static
tipeString
secara teoritis menjadi mungkin dengan Rust 1.31 ketikaconst fn
fitur itu dirilis. Sayangnya, satu-satunya fungsi const yang mengembalikan aString
isString::new()
saat, dan itu masih di belakang gerbang fitur (sehingga Rust malam diperlukan untuk saat ini).Jadi kode berikut melakukan konversi yang diinginkan (menggunakan nightly) ... dan sebenarnya tidak memiliki penggunaan praktis kecuali untuk kelengkapan menunjukkan bahwa itu mungkin dalam kasus tepi ini.
#![feature(const_string_new)] static MY_STRING: String = String::new(); fn do_something(_: &'static str) { // ... } fn main() { do_something(&MY_STRING); }
sumber