Cela ne semble ni possible ni souhaitable. 'staticdurée de vie impliquerait que la chaîne ne soit jamais désallouée, c'est-à-dire une fuite de mémoire. Pourquoi avez-vous besoin &'static strau lieu de &'a strcertains appropriés 'a?
3
À quoi cela ressemblerait-il pour le convertir en &'a str alors?
Christoph
Via as_slice. Il serait plus facile d'aider si vous décriviez le problème concret que vous essayez de résoudre et les problèmes que vous rencontrez en le faisant.
Notez également SendStr, un type qui est soit une chaîne possédée, soit une chaîne statique.
Chris Morgan
Réponses:
132
Mis à jour pour Rust 1.0
Vous ne pouvez pas obtenir &'static strd'un Stringcar Strings peut ne pas vivre toute la durée de vie de votre programme, et c'est ce que &'staticsignifie la vie. Vous ne pouvez paramétrer une tranche que parString propre durée de vie.
Pour passer d'une Stringtranche à une autre, &'a strvous pouvez utiliser la syntaxe de découpage:
let s:String="abcdefg".to_owned();let s_slice:&str=&s[..];// take a full slice of the string
Alternativement, vous pouvez utiliser le fait qui Stringimplémente Deref<Target=str>et effectue un réemprunt explicite:
let s_slice:&str=&*s;// s : String // *s : str (via Deref<Target=str>)// &*s: &str
Il existe même une autre méthode qui permet une syntaxe encore plus concise, mais elle ne peut être utilisée que si le compilateur est capable de déterminer le type de cible souhaité (par exemple dans des arguments de fonction ou des liaisons de variables typées explicitement). Elle s'appelle deref coercion et permet d'utiliser uniquement l' &opérateur, et le compilateur insérera automatiquement une quantité appropriée de *s en fonction du contexte:
let s_slice:&str=&s;// okayfn take_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
Notez que ce modèle n'est pas unique pour String/ &str- vous pouvez l'utiliser avec chaque paire de types qui sont connectés Deref, par exemple, avec CString/ CStret OsString/ OsStrdepuis le std::ffimodule ou PathBuf/ Pathdepuis le std::pathmodule.
Dans Rust 1.10 au lieu de let s_slice: &str = &s[..];vous pouvez simplement faire ceci:let s_slice: &str = s.as_str();
Shnatsel
3
Parfois, la chaîne d'origine ne vit pas assez, comme dans un bloc match {...}. Cela conduira à un 's' does not live long enough error.
Dereckson
38
Vous pouvez le faire, mais cela implique une fuite de la mémoire du fichierString . Ce n'est pas quelque chose que vous devez faire à la légère. En fuyant la mémoire du String, nous garantissons que la mémoire ne sera jamais libérée (donc la fuite). Par conséquent, toute référence à l'objet interne peut être interprétée comme ayant la 'staticdurée de vie.
fn string_to_static_str(s:String)->&'staticstr{Box::leak(s.into_boxed_str())}fn main(){letmut s =String::new();
std::io::stdin().read_line(&mut s).unwrap();let s:&'staticstr= string_to_static_str(s);}
Stringgarantit que tant que l'objet n'a pas été abandonné, la mémoire reste vivante. Puisque les mem::forgetgaranties que l'objet ne sera jamais abandonné, nous avons la garantie que la référence au contenu strne sera jamais invalide. Ainsi, nous pouvons affirmer qu'il s'agit d'une 'staticréférence
oli_obk
1
Cela a été extrêmement utile pour mon application Rust, qui devait forcer un Stringdans un &'static strafin que les jetons créés à partir de l'original Stringsoient disponibles sur tous les threads. Sans cela, le compilateur Rust se plaindrait que ma Stringvie se terminait à la fin de la fonction principale, ce qui n'était pas suffisant car il n'avait pas la 'staticgarantie.
mmstick
1
@mmstick: la meilleure solution dans ce cas serait d'utiliser crossbeamet de cibler les threads
oli_obk
3
@mmstick: si vous placez toute votre application dans une portée crossbeam et créez la chaîne en dehors de la portée, vous obtenez exactement cela.
oli_obk
1
Cette réponse est géniale! Cela m'a dit à la fois comment créer sournoisement une tranche de corde statique et m'a convaincu de ne pas le faire! J'ai choisi de refactoriser mon application pour ne pas utiliser de tranches de chaîne statiques dans autant d'endroits.
Paul Chernoch
21
À partir de la version 1.26 de Rust, il est possible de convertir un Stringen &'static strsans utiliser de unsafecode:
Cela convertit l' Stringinstance en une boîte stret la fuit immédiatement. Cela libère toute capacité excédentaire que la chaîne peut actuellement occuper.
Notez qu'il y a presque toujours des solutions qui sont préférables aux objets qui fuient, par exemple en utilisant la crossbeamcrate si vous voulez partager l'état entre les threads.
TL; DR: vous pouvez obtenir un &'static strde a Stringqui lui-même a une 'staticdurée de vie.
Bien que les autres réponses soient correctes et très utiles, il existe un cas de bord (pas si utile), où vous pouvez en effet convertir un Stringen un &'static str:
La durée de vie d'une référence doit toujours être plus courte ou égale à la durée de vie de l'objet référencé. C'est-à-dire que l'objet référencé doit vivre plus longtemps (ou autant de temps) que la référence. Puisque 'staticsignifie toute la durée de vie d'un programme, une durée de vie plus longue n'existe pas. Mais une durée de vie égale sera suffisante. Donc, si un Stringa une durée de vie de 'static, vous pouvez en obtenir une &'static strréférence.
La création d'un statictype Stringest théoriquement devenue possible avec Rust 1.31 lorsque la const fnfonctionnalité a été publiée. Malheureusement, la seule fonction const retournant a Stringest String::new()actuellement, et elle est toujours derrière une porte de fonctionnalité (donc Rust nightly est requis pour le moment).
Ainsi, le code suivant effectue la conversion souhaitée (en utilisant la nuit) ... et n'a en fait aucune utilité pratique, sauf pour montrer que c'est possible dans ce cas de bord.
'static
durée de vie impliquerait que la chaîne ne soit jamais désallouée, c'est-à-dire une fuite de mémoire. Pourquoi avez-vous besoin&'static str
au lieu de&'a str
certains appropriés'a
?&'a str
alors?as_slice
. Il serait plus facile d'aider si vous décriviez le problème concret que vous essayez de résoudre et les problèmes que vous rencontrez en le faisant.SendStr
, un type qui est soit une chaîne possédée, soit une chaîne statique.Réponses:
Mis à jour pour Rust 1.0
Vous ne pouvez pas obtenir
&'static str
d'unString
carString
s peut ne pas vivre toute la durée de vie de votre programme, et c'est ce que&'static
signifie la vie. Vous ne pouvez paramétrer une tranche que parString
propre durée de vie.Pour passer d'une
String
tranche à une autre,&'a str
vous pouvez utiliser la syntaxe de découpage:Alternativement, vous pouvez utiliser le fait qui
String
implémenteDeref<Target=str>
et effectue un réemprunt explicite:Il existe même une autre méthode qui permet une syntaxe encore plus concise, mais elle ne peut être utilisée que si le compilateur est capable de déterminer le type de cible souhaité (par exemple dans des arguments de fonction ou des liaisons de variables typées explicitement). Elle s'appelle deref coercion et permet d'utiliser uniquement l'
&
opérateur, et le compilateur insérera automatiquement une quantité appropriée de*
s en fonction du contexte:Notez que ce modèle n'est pas unique pour
String
/&str
- vous pouvez l'utiliser avec chaque paire de types qui sont connectésDeref
, par exemple, avecCString
/CStr
etOsString
/OsStr
depuis lestd::ffi
module ouPathBuf
/Path
depuis lestd::path
module.la source
let s_slice: &str = &s[..];
vous pouvez simplement faire ceci:let s_slice: &str = s.as_str();
's' does not live long enough error
.Vous pouvez le faire, mais cela implique une fuite de la mémoire du fichier
String
. Ce n'est pas quelque chose que vous devez faire à la légère. En fuyant la mémoire duString
, nous garantissons que la mémoire ne sera jamais libérée (donc la fuite). Par conséquent, toute référence à l'objet interne peut être interprétée comme ayant la'static
durée de vie.la source
String
garantit que tant que l'objet n'a pas été abandonné, la mémoire reste vivante. Puisque lesmem::forget
garanties que l'objet ne sera jamais abandonné, nous avons la garantie que la référence au contenustr
ne sera jamais invalide. Ainsi, nous pouvons affirmer qu'il s'agit d'une'static
référenceString
dans un&'static str
afin que les jetons créés à partir de l'originalString
soient disponibles sur tous les threads. Sans cela, le compilateur Rust se plaindrait que maString
vie se terminait à la fin de la fonction principale, ce qui n'était pas suffisant car il n'avait pas la'static
garantie.crossbeam
et de cibler les threadsÀ partir de la version 1.26 de Rust, il est possible de convertir un
String
en&'static str
sans utiliser deunsafe
code:Cela convertit l'
String
instance en une boîtestr
et la fuit immédiatement. Cela libère toute capacité excédentaire que la chaîne peut actuellement occuper.Notez qu'il y a presque toujours des solutions qui sont préférables aux objets qui fuient, par exemple en utilisant la
crossbeam
crate si vous voulez partager l'état entre les threads.la source
TL; DR: vous pouvez obtenir un
&'static str
de aString
qui lui-même a une'static
durée de vie.Bien que les autres réponses soient correctes et très utiles, il existe un cas de bord (pas si utile), où vous pouvez en effet convertir un
String
en un&'static str
:La durée de vie d'une référence doit toujours être plus courte ou égale à la durée de vie de l'objet référencé. C'est-à-dire que l'objet référencé doit vivre plus longtemps (ou autant de temps) que la référence. Puisque
'static
signifie toute la durée de vie d'un programme, une durée de vie plus longue n'existe pas. Mais une durée de vie égale sera suffisante. Donc, si unString
a une durée de vie de'static
, vous pouvez en obtenir une&'static str
référence.La création d'un
static
typeString
est théoriquement devenue possible avec Rust 1.31 lorsque laconst fn
fonctionnalité a été publiée. Malheureusement, la seule fonction const retournant aString
estString::new()
actuellement, et elle est toujours derrière une porte de fonctionnalité (donc Rust nightly est requis pour le moment).Ainsi, le code suivant effectue la conversion souhaitée (en utilisant la nuit) ... et n'a en fait aucune utilité pratique, sauf pour montrer que c'est possible dans ce cas de bord.
la source