如何使用构建器模式生成的数据

Bra*_*avo 2 rust

我是 Rust 新手,这基本上是我尝试编写的第一个 Rust 代码。下面是我正在处理的有问题的代码的简化版本,但错误是完全相同的。

struct A {
    pub value : i32
}

impl A {
    pub fn new() -> Self {
        A {value : 0}
    }
}

struct B {
    vec_a : Vec<A>
}

impl B {
    pub fn new() -> Self {
        B {
            vec_a : Vec::new()
        }
    }
    pub fn create_A(&mut self) -> &mut A {
        let a = A::new();
        self.vec_a.push(a);
        let last_index = self.vec_a.len() - 1;
        &mut self.vec_a[last_index]
    }
}

fn main() {
    let mut b = B::new();
    let a1 : &mut A = b.create_A();
    let a2 : &mut A = b.create_A();
    
    println!("{}, {}", a1.value, a2.value);
}
Run Code Online (Sandbox Code Playgroud)

代码给出以下编译错误:

struct A {
    pub value : i32
}

impl A {
    pub fn new() -> Self {
        A {value : 0}
    }
}

struct B {
    vec_a : Vec<A>
}

impl B {
    pub fn new() -> Self {
        B {
            vec_a : Vec::new()
        }
    }
    pub fn create_A(&mut self) -> &mut A {
        let a = A::new();
        self.vec_a.push(a);
        let last_index = self.vec_a.len() - 1;
        &mut self.vec_a[last_index]
    }
}

fn main() {
    let mut b = B::new();
    let a1 : &mut A = b.create_A();
    let a2 : &mut A = b.create_A();
    
    println!("{}, {}", a1.value, a2.value);
}
Run Code Online (Sandbox Code Playgroud)

在我看来,编译器告诉我,使用 ofa1是不安全的,因为它是从 生成的b,但是bafter的另一个可变借用a1可能会发生变化b,因此 in 中的数据a1现在无效。我对这个错误的理解正确吗?如果是这样,我如何告诉编译器a1,它们a2是完全不同的部分,稍后b使用可以吗?a1

Rust Playground 中的代码

Fin*_*nis 5

是的,你的理解是正确的。a1是从 借用的b,虽然a1存在,但不能修改b

如果是这样,我如何告诉编译器 a1 和 a2 是 b 的完全不同的部分,并且稍后使用 a1 就可以了?

这是错误的,您认为这是可能的事实表明了借用检查器的价值。即使在 C++ 中,您的代码也将是未定义的行为。

将元素添加到向量可能会导致内存重新分配,从而使对该向量中元素的所有引用无效。在C++中也是一样的。

因此编译器是对的:你不能这样做。self.vec_a.push()可能会使您的a1参考资料无效。


即使不会发生重新分配,您的代码仍然不健全。

没有任何内容b记录对向量的引用。因此,如果您可以访问bwhile a1(&mut对 的引用b) 存在,则可以获得另一个引用&b.vec_a[0]。那么你就会同时拥有对同一个对象的引用&mut和引用,这是被禁止的/不合理的。&A


你想达到什么目的?我确信有一种更适合 Rust 的不同编程模式。您现在使用的根本不兼容 Rust。