【问题标题】:Struct with immutable reference to other struct具有对其他结构的不可变引用的结构
【发布时间】:2015-07-20 10:46:57
【问题描述】:

首先我想为这个标题不明确的菜鸟问题道歉,我对 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 方法中,使用对单个 A 对象的引用创建了几个 B 对象。

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

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 作为 mutable。为什么 new() 完成后可变借用不结束?实现我正在尝试的正确方法是什么?

【问题讨论】:

    标签: rust


    【解决方案1】:

    正如@AndreaP 所说,问题在于您的引用具有相同的生命周期。

    通常,您可以通过简单地拆分函数(一个 &amp; 和一个 &amp;mut)来解决这些问题。

    如果你真的需要这种模式,那么我想你正在寻找的是Cell/RefCell:http://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);
    }
    

    【讨论】:

    • 谢谢!你完全正确,我已经相应地修改了代码。
    【解决方案2】:

    借用未完成,因为您在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);
    }
    

    【讨论】:

    • 感谢您的回答。不幸的是,我的应用程序中的多个 B 对象都需要引用一个 A 对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-25
    • 1970-01-01
    • 1970-01-01
    • 2015-08-09
    相关资源
    最近更新 更多