【问题标题】:What are the differences when getting an immutable reference from a mutable reference with self-linked lifetimes?从具有自链接生命周期的可变引用获取不可变引用时有什么区别?
【发布时间】:2021-05-13 22:08:17
【问题描述】:
struct Foo01<'a> {
    val: u32,
    str: &'a String,
}

fn mutate_and_share_01<'a>(foo: &'a mut Foo01<'a>) -> &'a Foo01<'a> {
    foo
}

fn mutate_and_share_02<'a>(foo: &'a mut Foo01<'a>) -> &'a Foo01 {
    foo
}

fn mutate_and_share_03<'a>(foo: &'a mut Foo01) -> &'a Foo01<'a> {
    foo
}

fn main() {
    let mut foo = Foo01 { val: 16, str: &String::from("Hello ") };
    let foo_mut = &mut foo;

    //let loan = mutate_and_share_01(foo_mut);
    //let loan2 = mutate_and_share_01(foo_mut); //error

    //let loan = mutate_and_share_02(foo_mut);
    //let loan2 = mutate_and_share_02(foo_mut); //error

    let loan = mutate_and_share_03(foo_mut);
    let loan2 = mutate_and_share_03(foo_mut); //good
}

这些mutate_and_share 版本之间有什么区别?

【问题讨论】:

  • 一般来说,应该避免使用&amp;'a SomeType&lt;'a&gt; 模式,因为像这样将引用的生命周期链接到自身通常是没有意义的。并且可能会出现很多不明显的问题(123),尤其是在涉及可变引用时。

标签: rust lifetime


【解决方案1】:

在情况 1 和 2 中,您是说只要结构借用其参数,函数就会借用结构:

foo: &'a mut Foo01

这表示“foo 是从 'a 借来的”(&amp;'a mut)和“foo 借用它的参数为 'a”(Foo01&lt;'a&gt;)。

就 rustc 而言,这意味着调用此函数必然会永远借用输入,因为结构必然会在其整个生命周期内借用 输入,因此您会被锁定:您不能通过删除输入来“取消借用”输入,因此第二次调用永远无法工作。

在情况 3 中,您将 输出 的参数与内部借用相关联,这不是真的,但至少在这种情况下工作得很好。事实上,这两个生命是无关的:

fn mutate_and_share<'a, 'b>(foo: &'a mut Foo01<'b>) -> &'a Foo01<'b> {
    foo
}

还请注意,您的第三种情况仅适用,因为您从未使用 loan,因此在第二行执行之前立即将其删除。如果你这样做:

    let loan = mutate_and_share_03(foo_mut);
    let loan2 = mutate_and_share_03(foo_mut); //good
    print("{}", loan.val)

那么它不会编译,因为可变借用是重叠的。

哦,&amp;String 通常没用。 &amp;mut String 有一些用例,但任何时候您看到对 String 的不可变引用时,最好使用 &amp;str。和&amp;Vec&lt;T&gt;一样,没用,应该是&amp;[T]

【讨论】:

  • 让 foo_mut = &mut foo; // 一旦 mut 借用 mutate_and_share_03(foo_mut); //两次mut借为什么不发生借用错误
  • 因为非词法借用:由于您实际上并没有使用 loan 变量,编译器会立即删除它,借用结束,可以使用新的已创建。
  • 虽然你可以预料到第一次调用会“移动”可变引用,但在这些情况下,Rust 实际上会隐式地重新借用它(就好像你写了&amp;mut *foo_mut),所以它实际上创建了嵌套的子借位。见this older answer by Sven Marnach for more details
猜你喜欢
  • 2015-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-15
  • 1970-01-01
  • 1970-01-01
  • 2011-10-27
  • 1970-01-01
相关资源
最近更新 更多