【问题标题】:Is there a safe way for a struct to store a slice of a vector that will be modified outside the struct?结构是否有一种安全的方法来存储将在结构外部修改的向量切片?
【发布时间】:2020-09-27 19:46:47
【问题描述】:

我正在实现处理长度为k * n 的向量并创建 k 长度点 n 引用原始向量的切片:

struct Point<'a> {
    values: &'a [f32],
}

impl<'a> Point<'a> {
    pub fn new(values: &'a [f32]) -> Self {
        Point { values }
    }

    pub fn dist_euclidian(&self, point: &Point) -> Result<f32, &str> {
        unimplemented!()
    }
}

当我尝试测试它时:

#[test]
fn test_euclidian_distance() {
    let mut v1 = vec![7.0, 11.0];
    let mut v2 = vec![40.0, -27.0];
    let p1: Point = Point::new(&v1[..]);
    let p2: Point = Point::new(&v2[..]);

    assert!((p1.dist_euclidian(&p2).unwrap() - 50.32).abs() <= 0.01);

    v1[0] = 0.0;
    v1[1] = -4.0;
    v2[0] = 8.0;
    v2[1] = 100.0;

    assert!((p1.dist_euclidian(&p2).unwrap() - 104.3072).abs() <= 0.01);
}

我收到以下错误:


error[E0502]: cannot borrow `v1` as mutable because it is also borrowed as immutable
  --> src/k_means/point.rs:56:9
   |
51 |         let p1: Point = Point::new(&v1[..]);
   |                                     -- immutable borrow occurs here
...
56 |         v1[0] = 0.0;
   |         ^^ mutable borrow occurs here
...
61 |         assert!((p1.dist_euclidian(&p2).unwrap() - 104.3072).abs() <= 0.01);
   |                  -- immutable borrow later used here

error[E0502]: cannot borrow `v1` as mutable because it is also borrowed as immutable
  --> src/k_means/point.rs:57:9
   |
51 |         let p1: Point = Point::new(&v1[..]);
   |                                     -- immutable borrow occurs here
...
57 |         v1[1] = -4.0;
   |         ^^ mutable borrow occurs here
...
61 |         assert!((p1.dist_euclidian(&p2).unwrap() - 104.3072).abs() <= 0.01);
   |                  -- immutable borrow later used here

error[E0502]: cannot borrow `v2` as mutable because it is also borrowed as immutable
  --> src/k_means/point.rs:58:9
   |
52 |         let p2: Point = Point::new(&v2[..]);
   |                                     -- immutable borrow occurs here
...
58 |         v2[0] = 8.0;
   |         ^^ mutable borrow occurs here
...
61 |         assert!((p1.dist_euclidian(&p2).unwrap() - 104.3072).abs() <= 0.01);
   |                                    --- immutable borrow later used here

error[E0502]: cannot borrow `v2` as mutable because it is also borrowed as immutable
  --> src/k_means/point.rs:59:9
   |
52 |         let p2: Point = Point::new(&v2[..]);
   |                                     -- immutable borrow occurs here
...
59 |         v2[1] = 100.0;
   |         ^^ mutable borrow occurs here
60 | 
61 |         assert!((p1.dist_euclidian(&p2).unwrap() - 104.3072).abs() <= 0.01);
   |                                    --- immutable borrow later used here


有没有一种安全的方式来做我打算做的事情?

【问题讨论】:

标签: rust slice lifetime unsafe ownership


【解决方案1】:

不幸的是,Rust 的引用有一个类似于在其他语言中存储“按引用”的名称,但事实并非如此。 Rust 的引用适用于对数据的 临时 视图,当您希望将该数据的使用限制在某个范围内并防止其在该范围之外使用时。这与您在这里需要的相反。

如果你想保留一些东西,不要对它使用临时引用。改用拥有的值,可以永久存储和移动。 99% 的情况下,将引用放在结构中是错误的。

与其尝试保留临时借用的切片 &amp;'a [f32],不如存储拥有的 Vec&lt;f32&gt; 或拥有的切片 Box&lt;[f32]&gt;

如果您希望点具有二维,则使用字段、2 元素数组或元组 (f32, f32) 会更有效。如果您想要一个小但可变数量的维度,使用ArrayVec&lt;[f32; 4]&gt; 会更有效。

【讨论】:

    猜你喜欢
    • 2017-07-27
    • 2016-01-14
    • 2015-02-21
    • 1970-01-01
    • 2018-07-11
    • 1970-01-01
    • 2020-01-11
    相关资源
    最近更新 更多