首页 文章

具有对其他结构的不可变引用的struct

提问于
浏览
0

首先,我想为这个具有非特定 Headers 的noob问题道歉,我对Rust很新 .

无论如何,这里有一些(工作)代码:

struct A {
    data: i32
}

struct B<'s> {
    a: &'s A
}

impl<'s> B<'s> {
    fn new(reference: &'s A) -> B<'s> {
        B {
            a: reference
        }
    }
}

fn main() {
    let a1 = A{data: 0};
    let b1 = B::new(&a1);
    let b2 = B::new(&a1);
}

有一个带有一些数据的结构A和一个包含对A的不可变引用的结构B.在main方法中,创建了几个B对象,引用了单个A对象 .

现在我只想改变一件事:在B :: new()方法中我想在使用它作为B的不可变成员之前修改'reference'的数据 . 我试过这样:

struct A {
    data: i32
}

struct B<'s> {
    a: &'s A
}

impl<'s> B<'s> {
    fn new(reference: &'s mut A) -> B<'s> {

        // Modify data
        reference.data += 1;

        B {
            a: reference
        }
    }
}

fn main() {
    let mut a1 = A{data: 0};
    let b1 = B::new(&mut a1);
    let b2 = B::new(&mut a1);
}

但是编译器不会让我,错误:不能一次多次使用 a1 作为可变的 . 为什么没有't the mutable borrow over once new() has finished? What would be the proper way to achieve what I'尝试?

2 回答

  • 1

    借用尚未完成,因为您在 b1 中保持该引用存活 . 因此,当您尝试为 b2 执行相同操作时,借用仍然存在 .

    也许你只想要这个:

    fn main() {
        let mut a1 = A{data: 0};
        let mut a2 = A{data: 0};
        let b1 = B::new(&mut a1);
        let b2 = B::new(&mut a2);
    }
    
  • 0

    正如@AndreaP所说,这个问题是因为你的生命相同 .

    通常,只需拆分函数(一个 & 和一个 &mut )就可以解决这些问题 .

    如果你真的需要这种模式,那么我认为你在寻找的是 Cell / RefCellhttp://doc.rust-lang.org/std/cell/index.html

    编辑:感谢@Ker评论,我更新了代码,所以 B 确实持有对 A 的引用而不是它的副本 . 旧代码完全错了 .

    use std::cell::{Cell};
    
    #[derive(Debug)]
    struct A {
        data: Cell<i32>
    }
    
    #[derive(Debug)]
    struct B<'a> {
        a: &'a A
    }
    
    impl<'a> B<'a> {
        fn new(reference: &'a A) -> B<'a> {
            // Modify data
            reference.data.set(reference.data.get() + 1);
            B {
                a: reference
            }
        }
    }
    
    fn main() {
        let a1 = A{data: Cell::new(0)};
        let b1 = B::new(&a1);
        let b2 = B::new(&a1);
        println!("{}", a1.data.get());
        println!("{:?}", b1);
        println!("{:?}", b2);
    }
    

相关问题