如何将String转换为&'静态str

时间:2014-05-31 23:30:45

标签: rust

如何将String转换为&str?更具体地说,我想将其转换为str生命周期为static&'static str)。

4 个答案:

答案 0 :(得分:90)

针对Rust 1.0进行了更新

您无法从&'static str获取String,因为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强制,它允许只使用&运算符,编译器将根据上下文自动插入适当数量的*

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来自std::ffi模块的} / CStrOsString / OsStr或来自std::path模块的PathBuf / Path

答案 1 :(得分:20)

你可以这样做,但它涉及泄漏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);
}

答案 2 :(得分:14)

从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条板箱。

答案 3 :(得分:1)

TL; DR:您可以从&'static str获得String,而'static本身的寿命为String

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

引用的生存期必须始终短于或等于引用对象的生存期。即被引用的对象必须比引用的对象寿命更长(或相等)。由于String表示程序的整个生存期,因此不存在更长的生存期。但是相等的寿命就足够了。因此,如果'static的生存期为&'static str,则可以从中获得static引用。

从发布String功能开始,Rust 1.31可以创建类型为const fn的{​​{1}}。不幸的是,当前返回String的唯一const函数是String::new(),它仍然位于功能闸的后面(因此,现在需要Rust每晚)。

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

#![feature(const_string_new)]

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

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

fn main() {
    do_something(&MY_STRING);
}