作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想在拥有这些函数的结构上应用一些函数。
第一次尝试:
struct VM {
buffer: Vec<fn(&mut VM)>,
stack: Vec<isize>,
}
impl VM {
fn new() -> VM {
VM {
buffer: vec![VM::op_zero, VM::op_drop],
stack: vec![],
}
}
fn op_zero(&mut self) { self.stack.push(0); }
fn op_drop(&mut self) {
match self.stack.pop() {
Some(i) => println!("drop {}", i),
None => println!("stack underflow!")
}
}
fn evaluate(&mut self) {
for op in self.buffer {
op(self);
}
}
}
fn main() {
let mut vm = VM::new();
vm.evaluate();
}
这不起作用,因为移出了借用的内容。我在self.buffer
前加了一个&
,还是不行,因为self.buffer
也是借来的immutable。
fn evaluate(&mut self) {
for op in &self.buffer {
op(self);
}
}
第三次尝试有效,但有运行时边界检查数组索引的开销:
fn evaluate(&mut self) {
let len = self.buffer.len();
for i in 0..len {
let op = self.buffer[i];
op(self);
}
}
有没有更好的方法来绕过借用检查器?
最佳答案
您真的不应该尝试“绕过借用检查器”。它阻止您这样做,因为无法保证您调用的 op
不会与您尝试迭代的缓冲区混淆。事实上,您的最终代码存在同样的问题:op
可能截断 缓冲区,当您尝试读取超过向量末尾时导致 panic 。
一种安全的方法是在评估时换出 buffer
。假设您不打算多次评估相同的指令序列:
fn evaluate(&mut self) {
use std::mem;
for op in mem::replace(&mut self.buffer, vec![]) {
op(self);
}
}
在这种情况下,调用的op
可以修改新缓冲区,而不会干扰evaluate
。
关于iterator - 在拥有这些函数的结构上应用一些函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34564944/
我是一名优秀的程序员,十分优秀!