Как мне преобразовать String
в &str
? Более конкретно, я хотел бы преобразовать его в str
со static
временем жизни (&'static str
).
Как преобразовать строку в & 'static str
Ответ 1
Обновлено для Rust 1.0
Вы не можете получить &'static str
из String
, потому что String
не проживает всю жизнь вашей программы и что означает &'static
lifetime. Вы можете получить только срез, параметризованный String
собственным временем жизни от него.
Чтобы перейти от String
к фрагменту &'a str
, вы можете использовать синтаксис разрезания:
let s: String = "abcdefg".to_owned();
let s_slice: &str = &s[..]; // take a full slice of the string
В качестве альтернативы вы можете использовать тот факт, что String
реализует Deref<Target=str>
и выполняет явное переопределение:
let s_slice: &str = &*s; // s : String
// *s : str (via Deref<Target=str>)
// &*s: &str
Существует еще один способ, который позволяет использовать еще более сжатый синтаксис, но его можно использовать только в том случае, если компилятор может определить желаемый тип целевого объекта (например, в аргументах функции или явно введенных переменных). Он называется принуждением deref и позволяет использовать только оператор &
, и компилятор автоматически вставляет соответствующее количество *
в зависимости от контекста:
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
Обратите внимание, что этот шаблон не уникален для String
/&str
- вы можете использовать его с каждой парой типов, которые связаны через Deref
, например, с помощью CString
/CStr
и OsString
/OsStr
из std::ffi
или PathBuf
/Path
из std::path
.
Ответ 2
Вы можете сделать это, но это включает в себя утечку памяти String
. Это не то, что вы должны делать слегка. Утечка памяти String
гарантирует, что память никогда не будет освобождена (таким образом, утечка). Поэтому любые ссылки на внутренний объект могут быть интерпретированы как имеющие '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);
}
Ответ 3
Начиная с версии Rust 1.26, можно преобразовать String
в &'static str
String
без использования unsafe
кода:
fn string_to_static_str(s: String) -> &'static str {
Box::leak(s.into_boxed_str())
}
Это преобразует экземпляр String
в упакованный str
и сразу же пропускает его. Это освобождает всю избыточную емкость, которую строка может занимать в настоящее время.
Обратите внимание, что почти всегда есть решения, которые предпочтительнее протекающих объектов, например, использование ящика с crossbeam
балкой, если вы хотите разделить состояние между потоками.
Ответ 4
TL; DR: вы можете получить &'static str
String
из String
которая сама имеет 'static
время жизни.
Хотя другие ответы верны и наиболее полезны, есть (не очень полезный) край, в котором вы действительно можете преобразовать String
в &'static str
:
Время жизни ссылки всегда должно быть короче или равно времени жизни ссылочного объекта. Т.е. указанный объект должен жить дольше (или равным долго), чем ссылка. Так как 'static
означает всю жизнь программы, более длинная жизнь не существует. Но равного времени жизни будет достаточно. Таким образом, если у String
есть время жизни 'static
, вы можете получить ссылку &'static str
.
Создание static
типа String
теоретически стало возможным с Rust 1.31, когда была выпущена функция const fn
. К сожалению, единственной константной функцией, возвращающей String
является String::new()
, и она все еще за функциональными воротами (так что сейчас требуется ночная обработка Rust).
Таким образом, следующий код выполняет желаемое преобразование (используя ночной режим)... и фактически не имеет практического применения, за исключением полноты показа, что это возможно в этом крайнем случае.
#![feature(const_string_new)]
static MY_STRING: String = String::new();
fn do_something(_: &'static str) {
// ...
}
fn main() {
do_something(&MY_STRING);
}