我是Rust的新手,我很难理解一些引用/borrow 行为.

下面是一个无法编译的代码片段.我正在try 创建一个由u64个"切片"组成的数组,我想修改它们的值,然后稍后访问:

fn main() {
    // Initialize an array of "slices" with dummy data
    let mut refs: [&[u64]; 4] = [&[0; 2]; 4];

    // Write some computed values to the array
    for i in 0..refs.len() {
        // ...
        // some computation to get `x` and `y`
        // ...
        let data: [u64; 2] = [x as u64, y as u64];
        let data_ref: &[u64] = &data;
        refs[i] = data_ref;
    }

    // Read the computed values from the array
    println!("{}", refs[3][0]);
}

编译器返回:

error[E0597]: `data` does not live long enough
  --> src\main.rs:8:32
   |
7  |         let data: [u64; 2] = [x as u64, y as u64];
   |             ---- binding `data` declared here
8  |         let data_ref: &[u64] = &data;
   |                                ^^^^^ borrowed value does not live long enough
9  |         refs[i] = data_ref;
10 |     }
   |     - `data` dropped here while still borrowed
...
13 |     println!("{}", refs[3][0]);
   |                    ------- borrow later used here

虽然我知道data的作用域是在for循环中,并且它将不再存在于for循环之外(因此将refs[i]设置为引用data应该会导致编译器错误,因为refs的生命周期 超过data),但我不确定是否有其他方法可以正确设置refs的值.

从这样的数组中声明、初始化然后读取"切片"值的适当("Rust ")方式是什么?

推荐答案

问题是切片引用了"别处"的数据.他们也不能真的比他们引用的数据更长久.

如果你定义

let data: [u64; 2] = [x as u64, y as u64];

在您的循环中,每次迭代都会有data个死亡.因此

你不能有

let data_ref: &[u64] = &data;
refs[i] = data_ref;

因为当循环结束时,它将使refs包含对不再存在的一段数据的引用(data).

在你的例子中,你可以用两个元素的数组替换切片,像这样:

fn main() {
    let mut arrays = [[0; 2]; 4];

    // Write some computed values to the array
    for i in 0..arrays.len() {
        // ...
        // some computation to get `x` and `y`
        // ...
        let x = 1;
        let y = 2;
        arrays[i] = [x, y];
    }

    // Read the computed values from the array
    println!("{}", arrays[3][0]);
}

代码打印1.

如果您确实需要一个切片数组(例如,当您从外部获得refs时),我认为您可能需要将数据复制到切片中,如下所示:

(编辑:在德雷瓦茨的笔记后面增加了显式的[&mut [u64]; 4]类型)

fn main() {
    // Initialize an array of "slices" with dummy data
    // The array doesn't need to be mutable (we don't modify it)
    // The slices have to be mutable (we modify them)
    let refs: [&mut [u64]; 4] = [&mut [0; 2], &mut [0; 2], &mut [0; 2], &mut [0; 2]];

    // Write some computed values to the array
    for i in 0..refs.len() {
        // ...
        // some computation to get `x` and `y`
        // ...
        let x = 1;
        let y = 2;
        refs[i].copy_from_slice(&[x, y]);
    }

    // Read the computed values from the array
    println!("{}", refs[3][0]);
}

(我有这个难看的[&mut [0; 2], &mut [0; 2], &mut [0; 2], &mut [0; 2]]表单,因为[&mut [0; 2]; 4]不起作用-可变的数组引用不是Copy,所以用这种方式初始化refs不是那么容易).

有关详细信息,请参阅copy_from_slice documentation.

Rust相关问答推荐

如何在Rust中在屏幕中间打印内容?

如何从Rust记录WASM堆内存使用情况?

将已知大小的切片合并成一个数组,

用 rust 蚀中的future 展望 struct 的future

Gtk4-rs:将监视器作为gdk::monitor获取,而不是作为glib::对象获取

为什么我们需要std::thread::scope,如果我们可以使用thread.join()在函数的生命周期内删除引用?

定义只有一些字段可以缺省的 struct

为什么rustc会自动降级其版本?

为什么不';t(&;mut-iter).take(n)取得iter的所有权?

如何对一个特征的两个实现进行单元测试?

使用 pyo3 将 Rust 转换为 Python 自定义类型

为什么我们有两种方法来包含 serde_derive?

如何保存指向持有引用数据的指针?

使用 Rust 从 Raspberry Pi Pico 上的 SPI 读取值

有什么办法可以追踪泛型的单态化过程吗?

在 Rust 中,Weak 如何知道内部值何时被删除?

将 `&T` 转换为新类型 `&N`

返回引用字符串的future

如何为返回正确类型的枚举实现 get 方法?

Rust 跨同一文件夹中文件的可见性