如何将临时字符串转换为&str?

时间:2019-03-13 22:01:34

标签: rust format lifetime

我希望将使用String宏创建的format!转换为&str并使用let绑定将其分配给一个值:

fn main() {
    let my_bool = true;
    let other = String::from("my_string");
    let result = if my_bool {
        format!("_{}", other).as_str()
    } else {
        "other"
    };

    println!("{}", result);
}

Rust Playground

执行此操作时,编译器抱怨临时String值在语句末尾释放(根据我的理解),这意味着我无法动态创建{{1 }}:

&str

我一直在试图了解Rust的生命周期系统,但是我无法真正围绕这个系统。 Rust提出以下建议:

error[E0716]: temporary value dropped while borrowed
 --> src/main.rs:5:9
  |
4 |     let result = if my_bool {
  |         ------ borrow later stored here
5 |         format!("_{}", other).as_str()
  |         ^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
6 |     } else {
  |     - temporary value is freed at the end of this statement
  |

我将 = note: consider using a `let` binding to create a longer lived value 包裹在format!("_{}", other)装订中:

let

但是它似乎无法解决问题,因为当我在此绑定上调用fn main() { let my_bool = true; let other = String::from("my_string"); let result = if my_bool { let s = format!("_{}", other); s.as_str() } else { "other" }; println!("{}", result); } 时,它仍然抱怨借入的值寿命不足:

as_str()

当我省略整个error[E0597]: `s` does not live long enough --> src/main.rs:6:9 | 4 | let result = if my_bool { | ------ borrow later stored here 5 | let s = format!("_{}", other); 6 | s.as_str() | ^ borrowed value does not live long enough 7 | } else { | - `s` dropped here while still borrowed 时,此方法有效,但我宁愿不这样做,因为这会在原始代码库中引起很多麻烦。

此外,这似乎有点不合时宜,因为那时我仍然不知道为什么会失败。

我将如何系统地解决此问题?

1 个答案:

答案 0 :(得分:4)

&str是一个借入的字符串,因此您不能从临时String中获得一个字符串,否则引用将超出其绑定的值。

但是,您可以使用Cow类型来执行您想要的操作:

use std::borrow::Cow;

fn main() {
    let my_bool = true;
    let other = String::from("my_string");
    let result = if my_bool {
        Cow::Owned(format!("_{}", other))
    } else {
        Cow::Borrowed("other")
    };

    assert_eq!("_my_string", result);
}

Cow(对于写入时克隆)是一个enum,它拥有或借用数据。在这种情况下,result的类型为Cow<str>

您可以通过编写以下代码来简化表示法:

let result = if my_bool {
    format!("_{}", other).into()
} else {
    Cow::Borrowed("other")
};

或(样式):

let result: Cow<str> = if my_bool {
    format!("_{}", other).into()
} else {
    "other".into()
};