rust - 将字符串克隆到特定的生命周期

标签 rust ownership-semantics

我目前正在尝试用 Rust 编写一个小的命令行应用程序,但我在生命周期方面遇到了瓶颈。

extern crate clap;
use self::clap::{App, Arg};
use std::env;

impl<'p> Params<'p> {
    fn get_username_arg<'r>() -> Arg<'r, 'r> {
        let mut arg = Arg::with_name("Username")
            .short("u")
            .long("username")
            .takes_value(true);
        match env::var("USERNAME") {
            Ok(username) => {
                // How do I pass `username` to default_value?
                arg.default_value(username)
            }
            Err(e) => arg.required(true),
        }
    }
    // More code below...
}

问题是我试图将 username 传递给默认值方法,这需要 str 的生命周期为 'r。我试过克隆,但我不知道如何告诉它克隆的生命周期是多少。我尝试了以下几行:

let cln = (&*username).clone::<'r>();
arg.default_value(username)

出于某种原因,它现在告诉我 username 的生命周期不够长,尽管自从我克隆了数据后这应该无关紧要。

所以我的问题是,我该如何进行编译?

编辑:我想补充一点,除了生命周期参数之外,签名保持不变对我来说很重要。我不介意进行昂贵的操作(例如克隆)来完成这项工作。

最佳答案

malbarbo has provided some good solutions ,但我想讨论非工作代码的某些方面。

让我们从函数签名开始:

fn get_username_arg<'r>() -> Arg<'r, 'r> {

这表示“对于此函数的调用者选择的任何生命周期,我将返回一个Arg,其中包含将持续那么长时间的引用”。这是一个很难坚持的 promise ,因为调用者可能会请求满足 'static 的东西。生命周期,一个比调用 main 持续更长的值!事实上,您可以履行“任何一生”义务的唯一方法是返回 'static 的东西。 .

这是一个非常好的迹象,表明将会出现问题。另见 Why can't I store a value and a reference to that value in the same struct? ,它将这种情况显示为构造函数。许多人跳到试图返回 String连同 &str ,因此该答案也可能使该途径短路。 ^_^

username doesn't live long enough, even though it shouldn't matter since I cloned the data.

username有一个非常具体的生命周期,而且是有限的。如果您查看一段代码,通常可以直接找出对象的生命周期:它是变量在不移动的情况下所在的 block 的范围。在您的示例中,username只存在于作为匹配臂的一部分的 block 中 Ok(username) => { // } .一旦该 block 退出,该值就会被销毁。

clone in this case has a signature of <'s>clone() -> &'s str if you remove elisions (and reify Self) according to my very limited understanding of Rust in general.

env::var返回 Result<String, VarError> ,然后您访问 Ok变体,制作username一个String . String implementation of clone 需要 &String并返回 String .我不确定 -> &'s str 在哪里会来自。

So if I clone with clone::<'r>() it should force the lifetime...

这是一个非常的常见错误。查看Do Rust lifetimes influence the semantics of the compiled program? (可能还有 Why are explicit lifetimes needed in Rust? )以获取一些背景信息。您不能更改某物的生命周期,除非重写您的代码以使引用的值具有更大的范围。生命周期语法反射(reflect)了变量的生命周期,它不控制它。没有(安全的)方法可以“强制”一生。

(&*username).clone has that signature I mean

如果我们取消引用并重新引用 String ,我们最终得到一个 &str .那&str将有一个对应于 String 多长时间的生命周期生活。这是有道理的,因为 &str只是指向 String .当 String被释放,&str将指向不再处于有效状态的内存。

关于rust - 将字符串克隆到特定的生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37502627/

相关文章:

json - Rust基于json中的枚举反序列化json

rust - 带有 eq_any 的子查询无法编译

rust - 无法返回对 flat_map 中临时值的引用

Swift unowned self leaking when 'owned' by a view being presented

c++ - 我的新 Unique_ptr 的所有权?

regex - 如何使用 regex crate 来匹配整个 INI 部分?

rust - 为什么在链表上调用 into_iter 时 self 不移动?

rust - Rust 中返回值的范围是什么?

c++ - 在 Delphi 中明确表达所有权