rust - 为什么我需要这些生命周期而不需要其他生命周期,如何知道正确的签名以及如何识别需要生命周期的参数?

标签 rust lifetime

这是我的第一段 Rust 代码。我将生命周期参数添加到内部函数只是因为编译器告诉我这样做。虽然我看懂了 Rust 书中的终身解释,但我不可能自己写这个签名。

fn transform_the_expression() {
    fn create_formula<'t>(formula: & mut HashMap<& str, &'t str>, input: &'t str, re: Regex)->std::borrow::Cow<'t, str>{
        let replacement = re.find(input).unwrap();
        formula.insert("1", replacement.as_str());
        let rest = re.replace(input, "1");
        return rest;
    }

    let input = "(a+(b*c))";
    use regex::Regex;
    let re = Regex::new(r"\([\w\d][/*+-^][\w\d]\)").unwrap();
    use std::collections::HashMap;
    let mut formula = HashMap::new();

    let result = create_formula(&mut formula, input, re);

    println!("result = {:?}", result);

}
  • 为什么签名中的这 3 个地方需要生命周期?
  • 为什么其他地方不需要它们?
  • 如果编译器不告诉我该做什么,我将如何编写正确的签名?
  • 如何识别需要生命周期的参数?

最佳答案

编译器很擅长告诉您何时需要指定生命周期,但不一定擅长让您知道哪些生命周期。

首先,值得一提的是每个引用都有 生命周期;只是有lifetime elision rules这说明如果您不指定它们,编译器将如何填充它们。

回到你的签名:

fn create_formula(formula: & mut HashMap<& str, &str>, input: &str, re: Regex)->std::borrow::Cow<_, str>

第一个绝对需要的生命是Cow<_, str>中的那个;你需要有一个生命周期来声明这个函数。有两种选择:声明一个,或使用 'static .在这种情况下,Cow可能指向 input 的一部分参数,所以你需要把它们绑在一起。首先,需要通过添加 <'t> 来声明新的生命周期。 (任何名称都可以)在函数名称之后,然后将其用于 input和返回类型:

fn create_formula<'t>(formula: & mut HashMap<& str, &str>, input: &'t str, re: Regex)->std::borrow::Cow<'t, str>

最后,您将借用 input 的部分内容进入HashMap .如果input生命周期(我们现在命名为 't )与 HashMap 无关值,有人可以传入比输入生命周期更长的 HashMap ,从而导致映射中出现悬空指针。所以我们也需要对其进行约束,给出最终版本:

fn create_formula<'t>(formula: & mut HashMap<&str, &'t str>, input: &'t str, re: Regex)->std::borrow::Cow<'t, str>

关键是函数签名需要让编译器相信所有引用的使用都是安全的,这通常意味着你必须在默认情况下明确不同引用参数(和生命周期参数类型)之间的关系(通过省略规则)不要说正确的话。

关于rust - 为什么我需要这些生命周期而不需要其他生命周期,如何知道正确的签名以及如何识别需要生命周期的参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42255868/

相关文章:

rust - 即使显式也无法推断值类型

rust - 如何在 Rust Cargo.toml 中执行基准测试

Rust:错误 [E0495]:由于需求冲突,无法推断出 autoref 的适当生命周期

rust - 这个实例看似如何超过其自身的参数生存期?

generics - 问号在类型参数绑定(bind)中意味着什么?

rust - Amethyst 的fixed_update 是否有Bevy 等效项?

csv - 如何附加到现有的 CSV 文件?

rust - 遍历中RefCell的循环引用借用

rust - 想办法解决 "...does not live long enough"

c# - 不同 ASP.NET MVC 组件中的对象作用域和生命周期是什么?