Isso não parece possível nem desejável. 'staticO tempo de vida implicaria que a string nunca seria desalocada, ou seja, um vazamento de memória. Por que você precisa em &'static strvez de &'a stralgum apropriado 'a?
3
Como seria convertê-lo em &'a str então?
Christoph
Via as_slice. Seria mais fácil ajudar se você descrevesse o problema concreto que está tentando resolver e os problemas que encontra ao fazer isso.
Observe também SendStrum tipo que é uma string de propriedade ou uma string estática.
Chris Morgan
Respostas:
132
Atualizado para Rust 1.0
Você não pode obter &'static strde um Stringporque Strings podem não durar toda a vida do seu programa, e é isso que &'staticsignifica vida. Você só pode obter uma fatia parametrizada por seu Stringpróprio tempo de vida.
Para ir de uma Stringfatia para uma fatia, &'a strvocê pode usar a sintaxe de fatia:
let s:String="abcdefg".to_owned();let s_slice:&str=&s[..];// take a full slice of the string
Como alternativa, você pode usar o fato que Stringimplementa Deref<Target=str>e executa um novo empréstimo explícito:
let s_slice:&str=&*s;// s : String // *s : str (via Deref<Target=str>)// &*s: &str
Existe ainda outra forma que permite uma sintaxe ainda mais concisa, mas ela só pode ser usada se o compilador for capaz de determinar o tipo de destino desejado (por exemplo, em argumentos de função ou vinculações de variáveis explicitamente digitadas). É chamado de deref coercion e permite usar apenas o &operador, e o compilador irá inserir automaticamente uma quantidade apropriada de *s com base no contexto:
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
Observe que este padrão não é exclusivo para String/ &str- você pode usá-lo com todos os pares de tipos que estão conectados por meio de Deref, por exemplo, com CString/ CStre OsString/ OsStrdo std::ffimódulo ou PathBuf/ Pathdo std::pathmódulo.
Em Rust 1.10, em vez de let s_slice: &str = &s[..];você pode simplesmente fazer isso:let s_slice: &str = s.as_str();
Shnatsel
3
Às vezes, a string original não vive o suficiente, como em um bloco de correspondência {...}. Isso levará a um 's' does not live long enough error.
Dereckson
38
Você pode fazer isso, mas envolve vazar a memória doString . Isso não é algo que você deve fazer levianamente. Ao vazar a memória do String, garantimos que a memória nunca será liberada (daí o vazamento). Portanto, qualquer referência ao objeto interno pode ser interpretada como tendo o 'statictempo de vida.
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);}
Stringgarante que, enquanto o objeto não for abandonado, a memória permanecerá viva. Uma vez mem::forgetque garante que o objeto nunca será eliminado, temos a garantia de que a referência ao contido strnunca será inválida. Assim, podemos afirmar que é uma 'staticreferência
oli_obk
1
Isso foi incrivelmente útil para o meu aplicativo Rust, que precisava forçar um Stringem um &'static strpara que tokens criados a partir do original Stringestivessem disponíveis em todos os threads. Sem isso, o compilador Rust reclamaria que meu Stringtinha um tempo de vida que terminava no final da função principal, o que não era bom o suficiente porque não tinha a 'staticgarantia.
mmstick
1
@mmstick: a melhor solução nesse caso seria usar crossbeamthreads com escopo
oli_obk
3
@mmstick: se você colocar seu aplicativo inteiro em um escopo de viga cruzada e criar a string fora do escopo, você obterá exatamente isso.
oli_obk
1
Essa resposta é ótima! Ambos me disseram como criar tortuosamente uma fatia de corda estática e me convenceram a não fazer isso! Optei por refatorar meu aplicativo para não usar fatias de string estáticas em tantos lugares.
Paul Chernoch de
21
A partir da versão 1.26 do Rust, é possível converter um Stringpara &'static strsem usar o unsafecódigo:
Isso converte a Stringinstância em uma caixa stre vaza imediatamente. Isso libera todo o excesso de capacidade que a string pode ocupar atualmente.
Observe que quase sempre há soluções que são preferíveis a objetos que vazam, por exemplo, usando a crossbeamcaixa se você deseja compartilhar o estado entre os threads.
TL; DR: você pode obter um &'static strde um Stringque tem uma 'staticvida inteira.
Embora as outras respostas sejam corretas e mais úteis, há um caso extremo (não tão útil), onde você pode de fato converter a Stringem &'static str:
O tempo de vida de uma referência deve ser sempre menor ou igual ao tempo de vida do objeto referenciado. Ou seja, o objeto referenciado deve viver mais (ou igual) do que a referência. Uma vez que 'staticsignifica toda a vida útil de um programa, não existe uma vida útil mais longa. Mas uma vida útil igual será suficiente. Portanto, se a Stringtiver uma vida útil de 'static, você poderá obter uma &'static strreferência dele.
A criação de um statictipo Stringteoricamente se tornou possível com o Rust 1.31 quando o const fnrecurso foi lançado. Infelizmente, a única função const retornando a Stringé String::new()atualmente, e ainda está atrás de um portão de recurso (então Rust nightly é necessário por enquanto).
Portanto, o código a seguir faz a conversão desejada (usando nightly) ... e, na verdade, não tem uso prático, exceto para a integridade de mostrar que é possível neste caso extremo.
'static
O tempo de vida implicaria que a string nunca seria desalocada, ou seja, um vazamento de memória. Por que você precisa em&'static str
vez de&'a str
algum apropriado'a
?&'a str
então?as_slice
. Seria mais fácil ajudar se você descrevesse o problema concreto que está tentando resolver e os problemas que encontra ao fazer isso.SendStr
um tipo que é uma string de propriedade ou uma string estática.Respostas:
Atualizado para Rust 1.0
Você não pode obter
&'static str
de umString
porqueString
s podem não durar toda a vida do seu programa, e é isso que&'static
significa vida. Você só pode obter uma fatia parametrizada por seuString
próprio tempo de vida.Para ir de uma
String
fatia para uma fatia,&'a str
você pode usar a sintaxe de fatia:Como alternativa, você pode usar o fato que
String
implementaDeref<Target=str>
e executa um novo empréstimo explícito:Existe ainda outra forma que permite uma sintaxe ainda mais concisa, mas ela só pode ser usada se o compilador for capaz de determinar o tipo de destino desejado (por exemplo, em argumentos de função ou vinculações de variáveis explicitamente digitadas). É chamado de deref coercion e permite usar apenas o
&
operador, e o compilador irá inserir automaticamente uma quantidade apropriada de*
s com base no contexto:Observe que este padrão não é exclusivo para
String
/&str
- você pode usá-lo com todos os pares de tipos que estão conectados por meio deDeref
, por exemplo, comCString
/CStr
eOsString
/OsStr
dostd::ffi
módulo ouPathBuf
/Path
dostd::path
módulo.fonte
let s_slice: &str = &s[..];
você pode simplesmente fazer isso:let s_slice: &str = s.as_str();
's' does not live long enough error
.Você pode fazer isso, mas envolve vazar a memória do
String
. Isso não é algo que você deve fazer levianamente. Ao vazar a memória doString
, garantimos que a memória nunca será liberada (daí o vazamento). Portanto, qualquer referência ao objeto interno pode ser interpretada como tendo o'static
tempo de vida.fonte
String
garante que, enquanto o objeto não for abandonado, a memória permanecerá viva. Uma vezmem::forget
que garante que o objeto nunca será eliminado, temos a garantia de que a referência ao contidostr
nunca será inválida. Assim, podemos afirmar que é uma'static
referênciaString
em um&'static str
para que tokens criados a partir do originalString
estivessem disponíveis em todos os threads. Sem isso, o compilador Rust reclamaria que meuString
tinha um tempo de vida que terminava no final da função principal, o que não era bom o suficiente porque não tinha a'static
garantia.crossbeam
threads com escopoA partir da versão 1.26 do Rust, é possível converter um
String
para&'static str
sem usar ounsafe
código:Isso converte a
String
instância em uma caixastr
e vaza imediatamente. Isso libera todo o excesso de capacidade que a string pode ocupar atualmente.Observe que quase sempre há soluções que são preferíveis a objetos que vazam, por exemplo, usando a
crossbeam
caixa se você deseja compartilhar o estado entre os threads.fonte
TL; DR: você pode obter um
&'static str
de umString
que tem uma'static
vida inteira.Embora as outras respostas sejam corretas e mais úteis, há um caso extremo (não tão útil), onde você pode de fato converter a
String
em&'static str
:O tempo de vida de uma referência deve ser sempre menor ou igual ao tempo de vida do objeto referenciado. Ou seja, o objeto referenciado deve viver mais (ou igual) do que a referência. Uma vez que
'static
significa toda a vida útil de um programa, não existe uma vida útil mais longa. Mas uma vida útil igual será suficiente. Portanto, se aString
tiver uma vida útil de'static
, você poderá obter uma&'static str
referência dele.A criação de um
static
tipoString
teoricamente se tornou possível com o Rust 1.31 quando oconst fn
recurso foi lançado. Infelizmente, a única função const retornando aString
éString::new()
atualmente, e ainda está atrás de um portão de recurso (então Rust nightly é necessário por enquanto).Portanto, o código a seguir faz a conversão desejada (usando nightly) ... e, na verdade, não tem uso prático, exceto para a integridade de mostrar que é possível neste caso extremo.
fonte