Это не кажется возможным или желательным. 'staticСрок службы будет означать, что строка никогда не будет освобождена, то есть утечка памяти. Зачем он нужен &'static strвместо какого- &'a strто подходящего 'a?
3
Как бы это выглядело, чтобы преобразовать это в &'a str то?
Кристоф
Via as_slice. Было бы легче помочь, если бы вы описали, какую конкретную проблему вы пытаетесь решить и с какими проблемами вы при этом сталкиваетесь.
Также обратите внимание SendStrна тип, который является либо собственной строкой, либо статической строкой.
Крис Морган
Ответы:
134
Обновлено для Rust 1.0
Вы не можете получить &'static strиз a, Stringпотому что Strings может не прожить всю жизнь вашей программы, и именно это &'staticозначает время жизни. Из него можно получить только срез, параметризованный 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 coercion, и он позволяет использовать только &оператор, и компилятор автоматически вставит соответствующее количество *s в зависимости от контекста:
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
Обратите внимание, что этот шаблон не уникален для String/ &str- вы можете использовать его с каждой парой типов, которые связаны Deref, например, с CString/ CStrи OsString/ OsStrиз std::ffiмодуля или PathBuf/ Pathиз std::pathмодуля.
В Rust 1.10 вместо этого let s_slice: &str = &s[..];можно просто сделать это:let s_slice: &str = s.as_str();
Шнацель
3
Иногда исходная строка недостаточно жива, как в блоке match {...}. Это приведет к созданию файла 's' does not live long enough error.
Dereckson
42
Вы можете это сделать, но это связано с утечкой памятиString . Это не то, что вам следует делать легкомысленно. Утечка памяти Stringгарантирует, что память никогда не будет освобождена (отсюда и утечка). Следовательно, любые ссылки на внутренний объект можно интерпретировать как имеющие время 'staticжизни.
Stringдает гарантию, что до тех пор, пока объект не был отброшен, память остается активной. Поскольку мы mem::forgetгарантируем, что объект никогда не будет удален, мы гарантируем, что ссылка на содержащийся strникогда не будет недействительной. Таким образом, мы можем утверждать, что это 'staticотсылка
oli_obk
1
Это было невероятно полезно для моего приложения на Rust, которому нужно было Stringпреобразовать a в a, &'static strчтобы токены, созданные из оригинала String, были доступны во всех потоках. Без этого компилятор Rust жаловался бы, что у меня Stringвремя жизни заканчивается в конце основной функции, что было недостаточно, потому что у него не было 'staticгарантии.
mmstick
1
@mmstick: лучшим решением в этом случае будет использование crossbeamпотоков с
ограниченным объемом
3
@mmstick: если вы поместите все свое приложение в область видимости crossbeam и создадите строку вне области видимости, вы получите именно это.
oli_obk
1
Отличный ответ! Он одновременно рассказал мне, как искусно создать статический фрагмент строки, и убедил меня не делать этого! Я решил реорганизовать свое приложение, чтобы не использовать статические строковые фрагменты во многих местах.
Пол Чернох
24
Начиная с версии 1.26 Rust, можно преобразовать Stringв &'static strбез использования unsafeкода:
Это преобразует Stringэкземпляр в коробку strи немедленно пропускает ее. Это освобождает всю избыточную емкость, которую строка может в настоящее время занимать.
Обратите внимание, что почти всегда есть решения, которые предпочтительнее протекающих объектов, например, использование crossbeamкорзины, если вы хотите разделить состояние между потоками.
TL; DR: вы можете получить объект, &'static strу Stringкоторого есть время 'staticжизни.
Хотя другие ответы верны и наиболее полезны, есть (не очень полезный) крайний случай, когда вы действительно можете преобразовать a Stringв a &'static str:
Время жизни ссылки всегда должно быть меньше или равно времени жизни объекта, на который указывает ссылка. Т.е. объект, на который указывает ссылка, должен существовать дольше (или равен), чем ссылка. Поскольку 'staticозначает весь срок службы программы, более длительного срока службы не существует. Но равной продолжительности жизни будет достаточно. Так что, если у a Stringесть время жизни 'static, вы можете получить &'static strот него ссылку.
Создание staticшрифта Stringтеоретически стало возможным в Rust 1.31, когда эта const fnфункция была выпущена. К сожалению, единственная функция const, возвращающая a, Stringв String::new()настоящее время находится за воротами функций (поэтому на данный момент требуется Rust nightly).
Итак, следующий код выполняет желаемое преобразование (с использованием nightly) ... и на самом деле не имеет практического применения, за исключением полноты демонстрации того, что это возможно в этом пограничном случае.
'static
Срок службы будет означать, что строка никогда не будет освобождена, то есть утечка памяти. Зачем он нужен&'static str
вместо какого-&'a str
то подходящего'a
?&'a str
то?as_slice
. Было бы легче помочь, если бы вы описали, какую конкретную проблему вы пытаетесь решить и с какими проблемами вы при этом сталкиваетесь.SendStr
на тип, который является либо собственной строкой, либо статической строкой.Ответы:
Обновлено для Rust 1.0
Вы не можете получить
&'static str
из a,String
потому чтоString
s может не прожить всю жизнь вашей программы, и именно это&'static
означает время жизни. Из него можно получить только срез, параметризованный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 coercion, и он позволяет использовать только
&
оператор, и компилятор автоматически вставит соответствующее количество*
s в зависимости от контекста: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
модуля.источник
let s_slice: &str = &s[..];
можно просто сделать это:let s_slice: &str = s.as_str();
's' does not live long enough error
.Вы можете это сделать, но это связано с утечкой памяти
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); }
источник
String
дает гарантию, что до тех пор, пока объект не был отброшен, память остается активной. Поскольку мыmem::forget
гарантируем, что объект никогда не будет удален, мы гарантируем, что ссылка на содержащийсяstr
никогда не будет недействительной. Таким образом, мы можем утверждать, что это'static
отсылкаString
преобразовать a в a,&'static str
чтобы токены, созданные из оригиналаString
, были доступны во всех потоках. Без этого компилятор Rust жаловался бы, что у меняString
время жизни заканчивается в конце основной функции, что было недостаточно, потому что у него не было'static
гарантии.crossbeam
потоков сНачиная с версии 1.26 Rust, можно преобразовать
String
в&'static str
без использованияunsafe
кода:fn string_to_static_str(s: String) -> &'static str { Box::leak(s.into_boxed_str()) }
Это преобразует
String
экземпляр в коробкуstr
и немедленно пропускает ее. Это освобождает всю избыточную емкость, которую строка может в настоящее время занимать.Обратите внимание, что почти всегда есть решения, которые предпочтительнее протекающих объектов, например, использование
crossbeam
корзины, если вы хотите разделить состояние между потоками.источник
TL; DR: вы можете получить объект,
&'static str
уString
которого есть время'static
жизни.Хотя другие ответы верны и наиболее полезны, есть (не очень полезный) крайний случай, когда вы действительно можете преобразовать a
String
в a&'static str
:Время жизни ссылки всегда должно быть меньше или равно времени жизни объекта, на который указывает ссылка. Т.е. объект, на который указывает ссылка, должен существовать дольше (или равен), чем ссылка. Поскольку
'static
означает весь срок службы программы, более длительного срока службы не существует. Но равной продолжительности жизни будет достаточно. Так что, если у aString
есть время жизни'static
, вы можете получить&'static str
от него ссылку.Создание
static
шрифтаString
теоретически стало возможным в Rust 1.31, когда этаconst fn
функция была выпущена. К сожалению, единственная функция const, возвращающая a,String
вString::new()
настоящее время находится за воротами функций (поэтому на данный момент требуется Rust nightly).Итак, следующий код выполняет желаемое преобразование (с использованием nightly) ... и на самом деле не имеет практического применения, за исключением полноты демонстрации того, что это возможно в этом пограничном случае.
#![feature(const_string_new)] static MY_STRING: String = String::new(); fn do_something(_: &'static str) { // ... } fn main() { do_something(&MY_STRING); }
источник