Comment convertir une String
en un &str
? Plus précisément, je voudrais le convertir en une str
avec la vie static
(&'static str
).
Mis à jour pour Rust 1.0
Vous ne pouvez pas obtenir &'static str
à partir d'une String
car String
s ne dure pas toute la vie de votre programme, et c'est ce que &'static
durée de vie signifie. Vous ne pouvez obtenir qu'une tranche paramétrée par String
propre durée de vie à partir de celle-ci.
Pour passer d'une String
à une tranche &'a str
, vous 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
Sinon, vous pouvez utiliser le fait que String
implémente Deref<Target=str>
et effectue un reborrowing explicite:
let s_slice: &str = &*s; // s : String
// *s : str (via Deref<Target=str>)
// &*s: &str
Il existe même une autre méthode permettant 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 explicitement typées). Il s’appelle deref coercion et permet d’utiliser uniquement l’opérateur &
. Le compilateur insère automatiquement une quantité appropriée de *
s en fonction du contexte:
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
Notez que ce modèle n'est pas unique pour String
/&str
- vous pouvez l'utiliser avec chaque paire de types connectés via Deref
, par exemple, avec CString
/CStr
et OsString
/OsStr
de std::ffi
module ou PathBuf
/Path
std::path
module.
Vous pouvez le faire, mais cela implique une fuite de la mémoire de String
. Ce n'est pas quelque chose que vous devriez faire à la légère. En fuyant la mémoire de la variable 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 durée de vie 'static
.
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);
}
À partir de Rust version 1.26, il est possible de convertir une String
en &'static str
sans utiliser le code unsafe
:
fn string_to_static_str(s: String) -> &'static str {
Box::leak(s.into_boxed_str())
}
Cela convertit l'instance String
en une str
encadrée et la perd immédiatement. Cela libère toute la capacité excédentaire actuellement occupée par la chaîne.
Notez qu'il existe presque toujours des solutions préférables aux objets présentant des fuites, par ex. utilisez la caisse crossbeam
si vous souhaitez partager l’état entre les threads.
TL; DR: vous pouvez obtenir un &'static str
à partir d'une String
qui a elle-même une durée de vie 'static
.
Bien que les autres réponses soient correctes et très utiles, il existe un cas Edge (pas très utile), dans lequel vous pouvez en effet convertir une String
en &'static str
:
La durée de vie d'une référence doit toujours être inférieure ou égale à la durée de vie de l'objet référencé. C'est à dire. l'objet référencé doit vivre plus longtemps (ou plus longtemps que la référence). Puisque 'static
correspond à la durée de vie complète d’un programme, il n’existe pas de durée de vie plus longue. Mais une durée de vie égale sera suffisante. Donc, si une String
a une durée de vie de 'static
, vous pouvez en obtenir une référence &'static str
.
La création d'une static
de type String
est devenue théoriquement possible avec Rust 1.31 lorsque la fonctionnalité const fn
a été publiée. Malheureusement, la seule fonction const retournant une String
est String::new()
pour le moment et elle est toujours derrière une porte de fonctionnalité (donc Rust nightly est requis pour l'instant).
Ainsi, le code suivant effectue la conversion souhaitée (en utilisant nocturne) ... et n'a en fait aucune utilisation pratique, si ce n'est qu'il est complet de montrer que cela est possible dans ce cas Edge.
#![feature(const_string_new)]
static MY_STRING: String = String::new();
fn do_something(_: &'static str) {
// ...
}
fn main() {
do_something(&MY_STRING);
}