如何将字符串转换为 & ‘ static str

如何将 String转换为 &str?更具体地说,我想把它转换成具有 static生命周期(&'static str)的 str

150404 次浏览

为 Rust 1.0更新

你不能从 String获得 &'static str,因为 String可能不会在你的程序的整个生命周期中存活,这就是 &'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

甚至还有另外一种方法可以使语法更简洁,但只有在编译器能够确定所需的目标类型(例如函数参数或显式类型的变量绑定)的情况下才能使用。它被称为 无诉强制,它只允许使用 &操作符,编译器将根据上下文自动插入适量的 *:

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/CStrOsString/OsStr,或者在 &str2模块中使用 PathBuf/Path

你可以做到这一点,但它涉及到 泄露了 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);
}

从 Rust 版本1.26开始,不使用 unsafe代码就可以将 String转换为 &'static str:

fn string_to_static_str(s: String) -> &'static str {
Box::leak(s.into_boxed_str())
}

这会将 String实例转换为一个装箱的 str并立即泄漏它。这将释放字符串当前可能占用的所有过剩容量。

请注意,几乎总有比泄漏对象更可取的解决方案,例如,如果希望在线程之间共享状态,则使用 crossbeam机箱。

DR: 你可以从 String得到一个 &'static str,它本身有一个 'static生命周期。

虽然其他的答案都是正确的,也是最有用的,但是还有一个(不太有用的)边缘情况,你可以把一个 String转换成一个 &'static str:

引用的生存期必须始终短于或等于被引用对象的生存期。也就是说,被引用的对象必须比引用活得更长(或者等长)。因为 'static意味着程序的整个生命周期,所以不存在更长的生命周期。但是一个相等的寿命就足够了。因此,如果一个 String的生命周期为 'static,您可以从中获得一个 &'static str引用。

在发布 const fn特性时,使用 Rust 1.31创建类型为 Stringstatic在理论上已经成为可能。不幸的是,目前返回 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);
}