我已经开始学习 Rust,并且正在尝试实现一个简单的一维元胞自动机。我想将自动机状态 (Board
) 表示为包含大小和两个不同向量(相同大小)的结构。我试过了:
struct Board {
n: usize,
cur: Vec<u32>,
next: Vec<u32>,
}
impl Board {
fn new(size: usize) -> Board {
Board {
n: size,
cur: vec![0;size],
next: vec![0;size],
}
}
}
到目前为止一切顺利。我也能够改变这两个向量。但是后来我希望能够交换两个向量(或者更确切地说是它们的引用),例如:
fn swap(&mut self) -> &Board {
let tmp = self.cur;
self.cur = self.next;
self.next = tmp;
self
}
它失败了,cannot move out of borrowed content [E0507]
我想我能理解。我还尝试了 mem::swap
,我在类似标题的问题中找到了它,但没有成功。
我怎样才能让这个例子起作用? (由于我是 Rust 的初学者,请毫不犹豫地提出不同的数据表示法)。
最佳答案
What's the problem?
您正在打洞您的数据:
fn swap(&mut self) -> &Board {
let tmp = self.cur; // 1
self.cur = self.next; // 2
self.next = tmp; // 3
self
}
如果我们逐行分析:
self.cur
现在未初始化self.next
现在未初始化- 一切再次变得洁净
如果由于某种原因在第 (3) 行进行更改以收紧情况之前计算被中断,则 self
现在中毒并可能导致各种讨厌的事情发生。值得注意的是,例如,它的析构函数可能会尝试两次释放内存。
理论上,您可以让编译器检查临时漏洞并毫无疑问地证明:
- 打洞时没有函数访问
self
- 到作用域的末尾,无论是正常到达还是展开,孔都被再次填满
确实在某些时候它被考虑过......但事实是它很复杂并且有现成的解决方法。
So?
答案在于 std::mem
,它公开函数以安全的方式执行此类低级操作。虽然函数本身是使用 unsafe
实现的,但它们依赖于对语言和运行时的理解来公开安全接口(interface)。
您会感兴趣的两个特定函数是:
replace
:将dest: &mut T
中的内容替换为src: T
,并返回之前包含在dest中的内容
swap
:交换其参数的内容
使用这两个简单而安全的原语,您可以避免在数据中打洞。
关于struct - 如何交换结构的两个字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35649968/