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


91

如何将a转换String为a &str?更具体地说,我想将其转换为str带有static生存期(&'static str)的。


这似乎是不可能的,也不可取。'static生存期意味着该字符串永远不会被释放,即发生内存泄漏。为什么需要&'static str代替&'a str一些合适的东西'a

3
将其转换成&'a str 当时的样子如何?
克里斯多夫(Christoph)

通过as_slice。如果您描述了您要解决的具体问题以及在解决过程中遇到的问题,将会更容易获得帮助。

另请注意SendStr,类型是拥有的字符串或静态字符串。
克里斯·摩根

Answers:


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强制,它允许使用just&运算符,并且编译器将*根据上下文自动插入适当数量的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/CStrOsString/OsStr来自std::ffi模块或PathBuf/Path来自std::path模块连接的每对类型。


29
在Rust 1.10中,let s_slice: &str = &s[..];您可以简单地执行以下操作:let s_slice: &str = s.as_str();
Shnatsel

3
有时,原始字符串不够用,就像在match {...}块中一样。这将导致's' does not live long enough error
Dereckson '16

41

您可以执行此操作,但这涉及到的内存泄漏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);
}

8
String保证只要没有删除对象,内存就会保持活动状态。由于可以mem::forget保证永远不会删除对象,因此可以保证对包含对象的引用str永远不会无效。因此,我们可以断言这是一个'static参考
oli_obk

1
这对于我的Rust应用程序非常有用,它需要将a强制String转换为a,&'static str以便从原始String线程创建的令牌将在所有线程中可用。没有这个,Rust编译器会抱怨我String的生命期在main函数的末尾结束,这还不够好,因为它没有'static保证。
mmstick

1
@mmstick:在这种情况下,更好的解决方案是使用crossbeam和限定范围的线程
oli_obk

3
@mmstick:如果将整个应用程序放入横梁范围并在范围之外创建字符串,则完全可以实现。
oli_obk

1
这个答案很棒!两者都告诉我如何异常创建静态字符串切片,并说服我不要这样做!我选择重构我的应用程序,使其在很多地方不使用静态字符串片段。
Paul Chernoch

22

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

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

这会将String实例转换为盒装实例,str并立即泄漏它。这将释放字符串当前可能占用的所有多余容量。

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


2

TL; DR:您可以&'static strString本身具有'static生命周期的a获得。

尽管其他答案是正确且最有用的,但是有一个(不太有用)边缘情况,您实际上可以将a转换String为a &'static str

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

理论上,在发布功能时,使用Rust 1.31可以创建astatic类型。不幸的是,只有const函数返回一个是目前,它仍然是一个功能门后(所以锈病每晚需要现在)。Stringconst fnStringString::new()

因此,以下代码进行了所需的转换(每晚使用)...并且实际上没有实际用途,只是完整地表明在这种情况下是可能的。

#![feature(const_string_new)]

static MY_STRING: String = String::new();

fn do_something(_: &'static str) {
    // ...
}

fn main() {
    do_something(&MY_STRING);
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.