rust by example指南显示了带迭代器的斐波那契数列的以下代码here:

fn next(&mut self) -> Option<u32> {
    let new_next = self.curr + self.next;
    let new_curr = mem::replace(&mut self.next, new_next);

    // 'Some' is always returned, this is an infinite value generator
    Some(mem::replace(&mut self.curr, new_curr))
}

我想了解与最直观的(如果你来自其他语言)相比,这有什么优势:

fn next(&mut self) -> Option<u32> {
    let tmp = self.next;
    self.next = self.curr + self.next;
    self.curr = tmp;
    Some(self.curr)
}

推荐答案

由于Rust的所有权,直接编写代码并不总是可能的.如果self.next正在存储非Copy类型(例如,Vec<T>用于任何类型T),则let tmp = self.next;正在按值从self中取出该值,即移动所有权,因此源不应可用.但是源代码位于引用后面,引用必须始终指向有效数据,因此编译器不能允许从&mut中移出:您会遇到类似cannot move out of dereference of `&mut`-pointer的错误.

replace通过unsafe代码绕过这些问题,在内部保证在replace返回时,任何失效都完全有效.

关于移动的更多信息,请参见this answer,关于swap函数的相关问题,请参见this question(replaceimplemented,内部使用the standard library's swap).

Rust相关问答推荐

使用nom将任何空白、制表符、白线等序列替换为单个空白

何时可以在Rust中退出异步操作?

如何从铁 rust 中呼唤_mm_256_mul_ph?

除了调用`waker.wake()`之外,我如何才能确保future 将再次被轮询?

为什么我们需要std::thread::scope,如果我们可以使用thread.join()在函数的生命周期内删除引用?

我无法理解Rust范围的定义(Rust Programming Language,第二版克拉布尼克和尼科尔斯)

详尽的匹配模式绑定

我可以用 Rust 编写一个不可变变量

通过mem::transmute将数组展平安全吗?

实现AsyncWrite到hyper Sender时发生生命周期错误

如何在 Emacs Elisp 中获得类似格式化的 LSP?

从嵌入式 Rust 中的某个时刻开始经过的时间

将 `&T` 转换为新类型 `&N`

为什么指定生命周期让我返回一个引用?

在 RefCell 上borrow

如何存储返回 Future 的闭包列表并在 Rust 中的线程之间共享它?

使用 `.` 将 T 转换为 &mut T?

为什么这个值在上次使用后没有下降?

如何在 Rust 的内置函数上实现特征?

在特征中返回一个 Self 类型的值