27

我不完全理解生命,但我认为b' 的生命将在self' 之前结束。

那么,如何编辑这段代码呢?我在内存中复制一些东西吗?如果我做一个新的实例,这个生命周期必须遵守这个案例。

pub struct Formater {
    layout: &'static str,
}

impl Formater {
    pub fn new(layout: &'static str) -> Formater {
        let regex = Regex::new(r"%\{([a-z]+)(?::(.*?[^\\]))?\}").unwrap();
        let b = regex.replace_all(layout, "{}");

        return Formater {
            layout: &b,
        };
    }
}

错误:

error: `b` does not live long enough
  --> src/format.rs:16:22
   |
16 |             layout: &b,
   |                      ^ does not live long enough
17 |         };
18 |     }
   |     - borrowed value only lives until here
   |
   = note: borrowed value must be valid for the static lifetime...
4

1 回答 1

16

的作用域bnew函数,所以当函数返回时,它的内存会被释放。但是您正试图b从该函数返回一个引用。如果 Rust 允许你这样做,那么唯一可能使用该引用的代码将在值无效后使用它。借用检查器保护您免受未定义行为的影响。

Make layoutto be&'static str听起来你让事情变得简单,但是期望动态分配的内存regex.replace_all是静态的是不合理的。在不进入unsafe代码的情况下,您应该将'static 生命周期中的任何内容视为编译时常量。例如,字符串文字。

正如其他人所说,您可能想layout成为String. AString与 类似&str,但它拥有底层证券str。这意味着当您移动 时String,底层证券str也随之移动。A&str是一个引用,并且不能比str它所指向的所有者的寿命长。


如果您真的希望它是&str,另一种但不太符合人体工程学的方法是让调用者new()拥有&str,并将其作为可变引用传递。

pub struct Formatter<'a> {
    layout: &'a str,
}

impl <'a> Formatter<'a> {
    pub fn new(layout: &'a mut &str) -> Formatter<'a> {
        let regex = Regex::new(r"%\{([a-z]+)(?::(.*?[^\\]))?\}").unwrap();
        *layout = regex.replace_all(layout, "{}");

        return Formatter {
            layout: layout,
        };
    }
}

这会将问题移到调用堆栈的上一层,这意味着您传递给的引用new将被new.

pub fn main() {
    let mut s = "blah %{blah}";
    {
        let formatter = Formatter::new(&mut s);
        println!("{:?}", formatter.layout); // "blah {}"
    }
    println!("{:?}", s); // "blah {}"
}

Nows由 拥有main,因此formatter只要在比 更小的范围内使用它就有效main

String但总的来说,我认为这种方法比较麻烦,除非你有充分的理由,否则你应该坚持下去。

于 2017-02-28T10:27:12.983 回答