Eso no parece posible ni deseable. 'staticEl tiempo de vida implicaría que la cadena nunca se desasignará, es decir, una pérdida de memoria. ¿Por qué necesitas en &'static strlugar de &'a stralgo apropiado 'a?
3
¿Cómo se vería convertirlo en &'a str entonces?
Christoph
Via 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.
También tenga en cuenta SendStr, un tipo que es una cadena propia o una cadena estática.
Chris Morgan
Respuestas:
134
Actualizado para Rust 1.0
No puede obtener &'static strde un Stringporque Stringes posible que s no viva durante toda la vida de su programa, y eso es lo que &'staticsignifica vida. Solo puede obtener un segmento parametrizado por su Stringpropia vida a partir de él.
Para pasar de un sector Stringa 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 Stringimplementa 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; // 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
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/ CStry OsString/ OsStrdesde std::ffimódulo o PathBuf/ Pathdesde std::pathmódulo.
En Rust 1.10 en lugar de let s_slice: &str = &s[..];simplemente puedes hacer esto:let s_slice: &str = s.as_str();
Shnatsel
3
En algún momento, la cadena original no vive lo suficiente, como en un bloque de coincidencia {...}. Eso conducirá a un 's' does not live long enough error.
Dereckson
42
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 'staticvida útil.
Stringgarantiza que, mientras el objeto no se haya caído, la memoria permanece viva. Dado mem::forgetque garantiza que el objeto nunca se eliminará, tenemos la garantía de que la referencia al contenido strnunca será inválida. Así podemos afirmar que es una 'staticreferencia
oli_obk
1
Esto fue increíblemente útil para mi aplicación Rust, que necesitaba Stringconvertir a en a &'static strpara que los tokens creados a partir del original Stringestuvieran disponibles en todos los hilos. Sin esto, el compilador de Rust se quejaría de que Stringtení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 'staticgarantía.
mmstick
1
@mmstick: la mejor solución en ese caso sería usar crossbeamsubprocesos con alcance
oli_obk
3
@mmstick: si pones toda tu aplicación en un alcance transversal y creas la cadena fuera del alcance, obtienes exactamente eso.
oli_obk
1
¡Esta respuesta es genial! ¡Ambos me dijeron cómo crear de manera tortuosa un segmento de cuerda estática y me convencieron de no hacerlo! Elegí refactorizar mi aplicación para no usar cortes de cadenas estáticas en tantos lugares.
Paul Chernoch
24
A partir de la versión 1.26 de Rust, es posible convertir un Stringa &'static strsin usar unsafecódigo:
Esto convierte la Stringinstancia en una caja stry 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 crossbeamcaja si desea compartir el estado entre subprocesos.
TL; DR: puede obtener un &'static strde un Stringque en sí tiene 'statictoda 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 Stringa 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 'staticsignifica toda la vida útil de un programa, no existe una vida útil más larga. Pero una vida igual será suficiente. Entonces, si Stringtiene una vida útil de 'static, puede obtener una &'static strreferencia de él.
Teóricamente, la creación de un statictipo se Stringha hecho posible con Rust 1.31 cuando const fnse lanzó la función. Desafortunadamente, la única función const que devuelve a Stringes 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.
'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.Respuestas:
Actualizado para Rust 1.0
No puede obtener
&'static str
de unString
porqueString
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 suString
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
implementaDeref<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 conectadosDeref
, por ejemplo, conCString
/CStr
yOsString
/OsStr
desdestd::ffi
módulo oPathBuf
/Path
desdestd::path
módulo.fuente
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 del
String
. Esto no es algo que deba hacer a la ligera. Al filtrar la memoria delString
, 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); }
fuente
String
garantiza que, mientras el objeto no se haya caído, la memoria permanece viva. Dadomem::forget
que garantiza que el objeto nunca se eliminará, tenemos la garantía de que la referencia al contenidostr
nunca será inválida. Así podemos afirmar que es una'static
referenciaString
convertir a en a&'static str
para que los tokens creados a partir del originalString
estuvieran disponibles en todos los hilos. Sin esto, el compilador de Rust se quejaría de queString
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 alcanceA partir de la versión 1.26 de Rust, es posible convertir un
String
a&'static str
sin usarunsafe
código:fn string_to_static_str(s: String) -> &'static str { Box::leak(s.into_boxed_str()) }
Esto convierte la
String
instancia en una cajastr
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.fuente
TL; DR: puede obtener un
&'static str
de unString
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, siString
tiene una vida útil de'static
, puede obtener una&'static str
referencia de él.Teóricamente, la creación de un
static
tipo seString
ha hecho posible con Rust 1.31 cuandoconst fn
se lanzó la función. Desafortunadamente, la única función const que devuelve aString
esString::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); }
fuente