iterator - 在拥有这些函数的结构上应用一些函数

标签 iterator rust lifetime

我想在拥有这些函数的结构上应用一些函数。

第一次尝试:

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 也是借用为不可变的。

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 可能截断缓冲区,从而在您尝试读取超过向量末尾时导致 panic 。 p>

一种安全的方法是在评估缓冲区时更换它。假设您不打算多次评估相同的指令序列:

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/

相关文章:

rust - 为什么借用仍然保留在 if let 的 else block 中?

rust - 如何将字符串连接到宏派生中的标识?

rust - 模式 `&Unspecified` 和 `&__Nonexhaustive` 未涵盖

vector - 需要矢量切片才能活得更久

generics - 如何为涉及对中间局部变量的引用的闭包指定生命周期边界?

c++ - 从全局 vector 中删除的元素的生命周期

java - 在 Android 的 Java 中将此字符串分解为键/值字符串的最简单方法是什么?

c++ - 如何使用 `llvm::ilist_iterator<NodeTy>::operator pointer() const` 方法?

c++ - 管理 InputIterator 和 OutputIterator 的 `operator*` 返回值的常量性的规则是什么?

c++ - 即使边界键不存在,我也可以迭代 std::map 键范围吗?