Rust 生命周期行为

问题描述 投票:0回答:1

我试图通过《Programming Rust》一书来理解生命周期,并在这里制作了一个自定义示例:

fn simple_fn(point: [&i32; 3]) -> (&i32, &i32) {
    (point[0], point[2])
}

fn main() {
    let mut point: [&i32; 3] = [&19, &18, &17];

    {
        let x = 3;
        point[1] = &x;
        point[1] = &10;
    }

    let t = simple_fn(point);
    println!("{:?}", t);
}

编译器返回错误:

error[E0597]: `x` does not live long enough
  --> src/main.rs:10:20
   |
9  |         let x = 3;
   |             - binding `x` declared here
10 |         point[1] = &x;
   |                    ^^ borrowed value does not live long enough
11 |         point[1] = &10;
12 |     }
   |     - `x` dropped here while still borrowed
13 |
14 |     let t = simple_fn(point);
   |                       ----- borrow later used here

我不明白,当我将

point[1]
重新分配给
&10
时,在将其分配给
x
之后,那么为什么
point[1]
的生命周期仍然限于
x
的生命周期?

rust lifetime
1个回答
0
投票

我认为困惑来自以下事实:

let mut point = &1;

{
    let x = 3;
    point = &x;
    point = &10;
}

println!("{:?}", point); // Prints `10`

以上是有效的,因为 Rust 可以推断

i
已被完全替换。所以
i
可以拥有
&10
的生命周期,而不是
&x


让我们用一个更容易理解的例子来演示为什么你的例子不起作用。

让我们考虑一个

Vec<&i32>
。一切保持不变,但我们不使用索引,而是使用
.push()

let mut point = Vec::new();

{
    let x = 3;
    point.push(&x);

    point.clear();

    point.push(&10);
}

println!("{:?}", point);

上面的代码可以编译吗?

不,它会导致与您遇到的错误完全相同的错误。为什么?嗯,现在可能更清楚了。是的,我们调用

.clear()
会导致
&x
被删除。然而,仅仅通过查看
clear()
的函数定义,编译器并不知道这一点。因此,与
Vec<&i32>
相关的生命周期仍然是编译器的最短(观察到的)生命周期,即
&x
的生命周期。


现在,当你这样做时:

points[1] = &x;

这实际上只是语法糖:

*point.index_mut(1) = &x;

再次强调,编译器并不知道,某些 fn index_mut()

 会延长容器的生命周期。
理论上,编译器中完全可能存在特殊情况,在您的情况下,当使用常量索引时,它可以延长容器的生命周期。然而,使用一些动态值来索引是更常见的,因此特殊情况最终可能会变得更加混乱。
    

© www.soinside.com 2019 - 2024. All rights reserved.