示例指南生锈显示了带有迭代器的斐波纳契数列的以下代码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)
}
答案 0 :(得分:12)
由于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以获取有关移动的更多信息,this question查看有关swap
功能的相关问题(replace
implemented使用the standard library's swap
内部{{3}}。