如何将String转换为&'static str

Chr*_*oph 69 rust

如何将a String转换为&str?更具体地说,我想将它转换为str带有staticlifetime(&'static str)的a.

Vla*_*eev 106

更新为Rust 1.0

你无法&'static str从a 获得,String因为String你的生活并不适合你的生活,这就是&'static生命的意义.您只能通过String自己的生命周期获取切片参数.

要从a String切换到切片,&'a str您可以使用切片语法:

let s: String = "abcdefg".to_owned();
let s_slice: &str = &s[..];  // take a full slice of the string
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用String实现Deref<Target=str>和执行显式重新扩展的事实:

let s_slice: &str = &*s;  // s  : String 
                          // *s : str (via Deref<Target=str>)
                          // &*s: &str
Run Code Online (Sandbox Code Playgroud)

甚至还有另一种方法允许更简洁的语法,但只有在编译器能够确定所需的目标类型时才能使用它(例如在函数参数或显式类型的变量绑定中).它被称为deref强制,它允许只使用&运算符,编译器将*根据上下文自动插入适当数量的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
Run Code Online (Sandbox Code Playgroud)

请注意,此模式对于String/ 不是唯一的&str- 您可以将它Deref用于通过(例如)CString/ CStrOsString/ OsStr来自std::ffi模块或PathBuf/ Path来自std::path模块连接的每对类型.

  • 在Rust 1.10而不是`let s_slice:&str =&s [...];`你可以简单地这样做:`让s_slice:&str = s.as_str();` (19认同)
  • 关于如何在 `&amp;str`、`String`、`&amp;[u8]` 和 `Vec&lt;u8&gt;` 之间进行转换的更一般答案可以在[此处](/sf/answers/2872432601/ )。 (7认同)
  • 有时,原始字符串不够活跃,就像在匹配{...}块中一样.这将导致's'没有足够长的错误. (3认同)

oli*_*obk 26

你可以做到,但它涉及泄漏的记忆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);
}
Run Code Online (Sandbox Code Playgroud)

  • `String`保证,只要对象没有被删除,内存就会保持活着.由于`mem :: forget`保证永远不会丢弃该对象,因此我们保证对包含的`str`的​​引用永远不会无效.因此我们可以断言它是一个"静态"引用 (5认同)
  • @mmstick:如果你将整个应用程序放入一个横梁范围并在范围外创建字符串,那么你就是这样. (3认同)
  • 这对我的 Rust 应用程序非常有用,它需要将 `String` 强制转换为 `&amp;'static str`,以便从原始 `String` 创建的令牌可以在所有线程中使用。没有这个,Rust 编译器会抱怨我的 `String` 的生命周期在 main 函数的末尾结束,这还不够好,因为它没有 `'static` 保证。 (2认同)

Sve*_*ach 15

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

fn string_to_static_str(s: String) -> &'static str {
    Box::leak(s.into_boxed_str())
}
Run Code Online (Sandbox Code Playgroud)

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

请注意,几乎总有一些解决方案优于泄漏对象,例如,crossbeam如果要在线程之间共享状态,请使用包.

  • 我遇到的一个用例是“clap”。我正在创建一个 arg 来指定要使用的线程数,默认值等于用户计算机上的逻辑核心数。`Arg::default_value` 接受一个 `&amp;str` 并只保留这个引用,这通常没问题,因为通常这个值是一个编译时常量。但在这种情况下并非如此,这意味着我需要在运行时创建一个 `&amp;'static str` 。这是我的问题的确切解决方案。 (5认同)

Zar*_*ony 6

&'static strTL;DR:你可以从 a 中得到 a String,它本身有'static生命周期。

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

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

理论上,当该功能发布时,Rust 1.31 就可以创建staticof 类型。不幸的是,目前唯一返回 a 的 const 函数是当前的,并且它仍然位于功能门后面(所以现在需要 Rust nightly)。Stringconst fnStringString::new()

因此,以下代码执行所需的转换(使用夜间)......并且除了完整地表明在这种边缘情况下是可能的之外,实际上没有实际用途。

#![feature(const_string_new)]

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

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

fn main() {
    do_something(&MY_STRING);
}
Run Code Online (Sandbox Code Playgroud)