价值不够长

彭灵俊*_*彭灵俊 10 lifetime rust borrowing

我不完全了解生命,但我认为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,
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

错误:

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...
Run Code Online (Sandbox Code Playgroud)

Pet*_*all 9

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

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

正如其他人所说,你可能想layout成为一个String.A String类似于&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,
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

现在s属于main,所以formatter只要它的使用范围小于main.

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

  • @Lunfel 引用是借用。这是参考中的参考。所以这是借上借。全部检查完毕。 (2认同)