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

标签 rust format lifetime

<分区>

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

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 值在语句末尾被释放(据我所知),这意味着我无法动态创建一个&str:

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
  |

我一直在努力理解 Rust 的生命周期系统,但我无法真正理解这个系统。 Rust 建议如下:

  = note: consider using a `let` binding to create a longer lived value

我将 format!("_{}", other) 包裹在 let 绑定(bind)中:

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);
}

但这似乎并没有解决问题,因为当我在此绑定(bind)上调用 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

这在我省略整个 if 时有效,但我宁愿不这样做,因为这会给原始代码库带来很多麻烦。

此外,这看起来确实像是一种逃避,因为那时我仍然不知道为什么会失败。

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

最佳答案

&str是一个借来的字符串,所以你不能从一个临时的 String 中得到一个,否则引用将比它绑定(bind)的值长。

有两种解决方案可以缓解这个问题:


您可以创建一个新变量来存储 String来自 if范围:

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

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

您可以使用 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()
};

关于rust - 如何将临时字符串转换为 &str?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55151837/

相关文章:

rust - 如何将已经构建的 rust 库添加到 cargo build 中?

Rust 生命周期 - 从 Arc 中的 RWLock 中的向量返回值

keyboard - 如何拦截击键?

windows - 如何使用批处理文件/脚本更改系统日期格式?

rust - 生命周期注释,或 &str vs String

function - 无法在有关 iron lib 的 fn 项目中捕获动态环境

r - 在 R 中粘贴 0 个常规和斜体文本

javascript - 使用 Javascript 在 PHP 中更改值

iterator - 如何从 &mut 迭代器中提取值?

rust - FuturesUnordered 的终身问题