价值不能持续很长时间 [英] Value does not live long enough

查看:69
本文介绍了价值不能持续很长时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不完全了解生命周期,但我认为b的生命周期将在self之前结束.

I don't completely understand lifetimes, but I think b's lifetime will end before self's.

那么,如何编辑此代码?我要复制内存中的内容吗?如果我创建一个新实例,则必须坚持这种情况.

So, how to edit this code? Do I copy something in memory? If I make a new instance, this lifetime must adhere to this case.

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...

推荐答案

b的范围是new函数,因此在该函数返回时将释放其内存.但是,您试图从该函数返回对b的引用.如果Rust允许您这样做,则可能使用该引用的唯一代码将在之后使用该值,该值无效.借阅检查器可以保护您免受不确定的行为的影响.

The scope of b is the new function, so its memory will be freed when the function returns. But you are trying to return a reference to b from that function. If Rust let you do this, the only code that could possibly use that reference would use it after the value is invalid. The borrow checker is protecting you from undefined behaviour.

使layout成为&'static str听起来很简单,但是期望从regex.replace_all动态分配的内存是静态的是不合理的.在不使用unsafe代码的情况下,您应该将'static生命周期中的所有内容都视为编译时常量.例如,字符串文字.

Making layout to be &'static str sounds like you are making things simple, but it is unreasonable to expect the dynamically allocated memory from regex.replace_all to be static. Without getting into unsafe code, you should consider anything in the 'static lifetime to be a compile-time constant. For example, a string literal.

正如其他人所说,您可能希望layout成为String. String&str类似,但是它拥有基础str.这意味着当您移动String时,底层的str也会随之移动. &str是引用,并且不能超过它所指向的str的所有者.

As others have said, you probably want layout to be a String. A String is similar to &str, but it owns the underlying str. That means when you move the String, the underlying str moves with it. A &str is a reference and must not outlive the owner of the str that it points to.

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

If you really want it to be &str, an alternative but less ergonomic approach is to have the caller of new() own the &str, and pass it in as a mutable reference.

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突变.

This moves the problem one layer up the call stack and means that the reference you pass to new will be mutated by new.

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

现在smain拥有,因此formatter有效,只要仅在小于main的范围内使用.

Now s is owned by main, so formatter is valid as long as it is used only in a smaller scope than main.

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

But overall, I think this method is messier and you should just stick with String unless you have a good reason.

这篇关于价值不能持续很长时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆