我该如何将一个String
转换为&str
?更具体地说,我想将它转换为一个具有static
生命周期的str
(&'static str
)。
我该如何将一个String
转换为&str
?更具体地说,我想将它转换为一个具有static
生命周期的str
(&'static str
)。
更新至 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
甚至还有一种更加简洁的语法,但只能在编译器能够确定所需目标类型的情况下使用(例如在函数参数或显式类型变量绑定中)。它被称为 deref coercion,允许仅使用 &
运算符,并且编译器会根据上下文自动插入适当数量的 *
:
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
连接的每对类型一起使用,例如来自std::ffi
模块的CString
/CStr
和OsString
/OsStr
或来自std.path
模块的PathBuf
/Path
。s.as_str()
来代替 let s_slice: &str = &s[..];
。这样做不仅更加简洁易懂,而且不会改变原有代码的含义。 - Shnatselmatch {...}
块中。这会导致一个's' does not live long enough error
的错误。 - DerecksonString
的内存。这不是你应该轻易做的事情。通过泄漏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
在其 API 中并不保证其指向的内存一定在堆上(据我所知,如果我错了请纠正我)。实际上,这可能是可以接受的,但你无法证明你不会使用已经被释放的内存,例如可能在栈上的内存。 - George HilliardString
保证只要对象没有被丢弃,内存就会一直存在。由于 mem::forget
保证对象永远不会被丢弃,我们可以确保所包含的 str
的引用永远不会无效。因此,我们可以断言它是一个 'static
引用。 - oli_obkString
转换成一个 &'static str
,以便从原始的 String
创建的令牌可以在所有线程中使用。如果没有这个转换,Rust 编译器会抱怨我的 String
生命周期结束于主函数的结尾,这是不够好的,因为它没有 'static
保证。 - user3704639从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
crate。
clap
库。我正在创建一个 arg(命令行参数),指定要使用多少个线程,其默认值等于用户机器上的逻辑核心数。Arg::default_value
接受一个 &str
并仅保留此引用,通常情况下这很好,因为通常该值是编译时常量。但在这种情况下不是这样,这意味着我需要在运行时创建一个 'static
字符串切片(&'static str
)。这正是解决我的问题的方法。 - cyqsimonTL;DR:你可以从具有 'static
生命周期的 String
中获取 &'static str
。
虽然其他答案是正确和最有用的,但有一种(不太有用的)边缘情况,你确实可以将一个 String
转换为 &'static str
:
引用的生命周期必须始终短于或等于所引用的对象的生命周期。也就是说,所引用的对象必须比引用本身活得更长(或者同样长)。因为 'static
意味着整个程序的生命周期,不存在更长的生命周期。但是相等的生命周期就足够了。因此,如果一个 String
具有 'static
生命周期,则可以从中获取 &'static str
引用。
使用 Rust 1.31 发布的 const fn
特性,理论上已经可以创建类型为 String
的 static
。不幸的是,目前唯一返回 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);
}
'static
生命周期意味着字符串永远不会被释放,即存在内存泄漏的风险。为什么您需要&'static str
而不是某个适当的'a
的&'a str
? - user395760&'a str
,会是什么样子? - Christophas_slice
。如果您描述您正在尝试解决的具体问题以及在解决问题时遇到的问题,那么帮助您将会更加容易。 - user395760SendStr
,这是一种类型,可以是拥有的字符串或静态字符串。 - Chris Morgan