How do I convert a String
into a &str
? More specifically, I would like to convert it into a str
with the static
lifetime (&'static str
).
问题:
回答1:
Updated for Rust 1.0
You cannot obtain &'static str
from a String
because String
s do not live for the entire life of your program, and that's what &'static
lifetime means. You can only get a slice parameterized by String
own lifetime from it.
To go from a String
to a slice &'a str
you can use slicing syntax:
let s: String = "abcdefg".to_owned();
let s_slice: &str = &s[..]; // take a full slice of the string
Alternatively, you can use the fact that String
implements Deref<Target=str>
and perform an explicit reborrowing:
let s_slice: &str = &*s; // s : String
// *s : str (via Deref<Target=str>)
// &*s: &str
There is even another way which allows for even more concise syntax but it can only be used if the compiler is able to determine the desired target type (e.g. in function arguments or explicitly typed variable bindings). It is called deref coercion and it allows using just &
operator, and the compiler will automatically insert an appropriate amount of *
s based on the context:
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
Note that this pattern is not unique for String
/&str
- you can use it with every pair of types which are connected through Deref
, for example, with CString
/CStr
and OsString
/OsStr
from std::ffi
module or PathBuf
/Path
from std::path
module.
回答2:
You can do it, but it involves leaking the memory of the String
. This is not something you should do lightly. By leaking the memory of the String
, we guarantee that the memory will never be freed (thus the leak). Therefore, any references to the inner object can be interpreted as having the 'static
lifetime.
use std::mem;
fn string_to_static_str(s: String) -> &'static str {
unsafe {
let ret = mem::transmute(&s as &str);
mem::forget(s);
ret
}
}
fn main() {
let mut s = String::new();
std::io::stdin().read_line(&mut s).unwrap();
let s: &'static str = string_to_static_str(s);
}
回答3:
As of Rust version 1.26, it is possible to convert a String
to &'static str
without using unsafe
code:
fn string_to_static_str(s: String) -> &'static str {
Box::leak(s.into_boxed_str())
}
This converts the String
instance into a boxed str
and immediately leaks it. This frees all excess capacity the string may currently occupy.
Note that there are almost always solutions that are preferable over leaking objects, e.g. using the crossbeam
crate if you want to share state between threads.