如何将 String转换为 &str?更具体地说,我想把它转换成具有 static生命周期(&'static str)的 str。
String
&str
static
&'static str
str
为 Rust 1.0更新
你不能从 String获得 &'static str,因为 String可能不会在你的程序的整个生命周期中存活,这就是 &'static生命周期的意义。您只能从它获得一个由 String自己的生存期参数化的片。
&'static
要从 String转换为片 &'a str,可以使用切片语法:
&'a str
let s: String = "abcdefg".to_owned(); let s_slice: &str = &s[..]; // take a full slice of the string
或者,您可以使用 String实现 Deref<Target=str>并执行显式的重新借用:
Deref<Target=str>
let s_slice: &str = &*s; // s : String // *s : str (via Deref<Target=str>) // &*s: &str
甚至还有另外一种方法可以使语法更简洁,但只有在编译器能够确定所需的目标类型(例如函数参数或显式类型的变量绑定)的情况下才能使用。它被称为 无诉强制,它只允许使用 &操作符,编译器将根据上下文自动插入适量的 *:
&
*
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连接的类型中使用它,例如,在 &str1模块中使用 CString/CStr和 OsString/OsStr,或者在 &str2模块中使用 PathBuf/Path。
Deref
CString
CStr
OsString
OsStr
PathBuf
Path
你可以做到这一点,但它涉及到 泄露了 String的内存。这件事你不能掉以轻心。通过泄漏 String的内存,我们保证内存永远不会被释放(因此泄漏)。因此,对内部对象的任何引用都可以解释为具有 'static生存期。
'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); }
从 Rust 版本1.26开始,不使用 unsafe代码就可以将 String转换为 &'static str:
unsafe
fn string_to_static_str(s: String) -> &'static str { Box::leak(s.into_boxed_str()) }
这会将 String实例转换为一个装箱的 str并立即泄漏它。这将释放字符串当前可能占用的所有过剩容量。
请注意,几乎总有比泄漏对象更可取的解决方案,例如,如果希望在线程之间共享状态,则使用 crossbeam机箱。
crossbeam
DR: 你可以从 String得到一个 &'static str,它本身有一个 'static生命周期。
虽然其他的答案都是正确的,也是最有用的,但是还有一个(不太有用的)边缘情况,你可以把一个 String转换成一个 &'static str:
引用的生存期必须始终短于或等于被引用对象的生存期。也就是说,被引用的对象必须比引用活得更长(或者等长)。因为 'static意味着程序的整个生命周期,所以不存在更长的生命周期。但是一个相等的寿命就足够了。因此,如果一个 String的生命周期为 'static,您可以从中获得一个 &'static str引用。
在发布 const fn特性时,使用 Rust 1.31创建类型为 String的 static在理论上已经成为可能。不幸的是,目前返回 String的常量函数只有 String::new(),而且它仍然处于特性门后面(因此现在需要每晚使用 Rust)。
const fn
String::new()
因此,下面的代码完成了所需的转换(使用夜间) ... 实际上没有任何实际用途,只是完整地显示了在这种边缘情况下它是可能的。
#![feature(const_string_new)] static MY_STRING: String = String::new(); fn do_something(_: &'static str) { // ... } fn main() { do_something(&MY_STRING); }