¿Cómo convierto a String
en a &str
? Más específicamente, me gustaría convertirlo en un str
con el static
tiempo de vida ( &'static str
).
Actualizado para Rust 1.0
No puede obtener &'static str
de un String
porque String
es posible que s no viva durante toda la vida de su programa, y eso es lo que &'static
significa vida. Solo puede obtener un segmento parametrizado por su String
propia vida a partir de él.
Para pasar de un sector String
a otro &'a str
, puede utilizar la sintaxis de corte:
let s: String = "abcdefg".to_owned();
let s_slice: &str = &s[..]; // take a full slice of the string
Alternativamente, puede usar el hecho de que String
implementa Deref<Target=str>
y realiza un représtamo explícito:
let s_slice: &str = &*s; // s : String
// *s : str (via Deref<Target=str>)
// &*s: &str
Existe incluso otra forma que permite una sintaxis aún más concisa, pero solo se puede usar si el compilador puede determinar el tipo de destino deseado (por ejemplo, en argumentos de función o enlaces de variables escritos explícitamente). Se llama coerción deref y permite usar solo el &
operador, y el compilador insertará automáticamente una cantidad adecuada de *
s según el contexto:
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
Tenga en cuenta que este patrón no es único para String
/ &str
; puede usarlo con cada par de tipos que estén conectados Deref
, por ejemplo, con CString
/ CStr
y OsString
/ OsStr
desde std::ffi
módulo o PathBuf
/ Path
desde std::path
módulo.
let s_slice: &str = &s[..];
simplemente puedes hacer esto:let s_slice: &str = s.as_str();
's' does not live long enough error
.
Puedes hacerlo, pero implica filtrar la memoria delString
. Esto no es algo que deba hacer a la ligera. Al filtrar la memoria del String
, garantizamos que la memoria nunca se liberará (por lo tanto, la fuga). Por lo tanto, cualquier referencia al objeto interno puede interpretarse como si tuviera la 'static
vida útil.
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);
}
String
garantiza que, mientras el objeto no se haya caído, la memoria permanece viva. Dado mem::forget
que garantiza que el objeto nunca se eliminará, tenemos la garantía de que la referencia al contenido str
nunca será inválida. Así podemos afirmar que es una 'static
referencia
String
convertir a en a &'static str
para que los tokens creados a partir del original String
estuvieran disponibles en todos los hilos. Sin esto, el compilador de Rust se quejaría de que String
tenía una vida útil que terminaba al final de la función principal, lo que no era lo suficientemente bueno porque no tenía la 'static
garantía.
crossbeam
subprocesos con alcance
A partir de la versión 1.26 de Rust, es posible convertir un String
a &'static str
sin usar unsafe
código:
fn string_to_static_str(s: String) -> &'static str {
Box::leak(s.into_boxed_str())
}
Esto convierte la String
instancia en una caja str
y la filtra inmediatamente. Esto libera todo el exceso de capacidad que la cadena pueda ocupar actualmente.
Tenga en cuenta que casi siempre hay soluciones que son preferibles a los objetos con fugas, por ejemplo, usar la crossbeam
caja si desea compartir el estado entre subprocesos.
TL; DR: puede obtener un &'static str
de un String
que en sí tiene 'static
toda la vida.
Aunque las otras respuestas son correctas y más útiles, hay un caso de borde (no tan útil), donde de hecho puede convertir String
a en a &'static str
:
La vida útil de una referencia siempre debe ser más corta o igual a la vida útil del objeto referenciado. Es decir, el objeto referenciado tiene que vivir más (o el mismo tiempo) que la referencia. Dado que 'static
significa toda la vida útil de un programa, no existe una vida útil más larga. Pero una vida igual será suficiente. Entonces, si String
tiene una vida útil de 'static
, puede obtener una &'static str
referencia de él.
Teóricamente, la creación de un static
tipo se String
ha hecho posible con Rust 1.31 cuando const fn
se lanzó la función. Desafortunadamente, la única función const que devuelve a String
es String::new()
actualmente, y todavía está detrás de una puerta de función (por lo que se requiere Rust nightly por ahora).
Entonces, el siguiente código hace la conversión deseada (usando todas las noches) ... y en realidad no tiene ningún uso práctico, excepto para mostrar que es posible en este caso de borde.
#![feature(const_string_new)]
static MY_STRING: String = String::new();
fn do_something(_: &'static str) {
// ...
}
fn main() {
do_something(&MY_STRING);
}
'static
El tiempo de vida implicaría que la cadena nunca se desasignará, es decir, una pérdida de memoria. ¿Por qué necesitas en&'static str
lugar de&'a str
algo apropiado'a
?&'a str
entonces?as_slice
. Sería más fácil ayudar si describiera el problema concreto que está tratando de resolver y los problemas que encuentra al hacerlo.SendStr
, un tipo que es una cadena propia o una cadena estática.