1 IterMut 很难搞定
从原理上说,Iter 与 IterMut 是完全相同的,但是 IterMut 很难搞定。
1.1 原始定义
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> { /* stuff */ }
}
1.2 去掉语法糖(生命周期注解省略)
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next<'b>(&'b mut self) -> Option<&'a T> { /* stuff */ }
// 这就是说:输出(返回值)的生命周期,与输入的生命周期无关!!!
// 所以,可以省略输入参数的生命周期注解
}
1.3 可以不断调用next()方法
let mut list = List::new();
list.push(1); list.push(2); list.push(3);
let mut iter = list.iter();
let x = iter.next().unwrap();
let y = iter.next().unwrap();
let z = iter.next().unwrap();
- 对共享引用没有问题:可以同时拥有很多共享引用
- 对独占(可变)引用不可行:独占引用是不相容的。结果就是:使用安全代码实现IterMut有些难。
2 首次尝试:完全复制Iter的代码,但是把所有共享引用的地方,改成独占引用
//=========== 3.6 IterMut ===========
//cargo test --features chap3_6 -- --nocapture iter_mut
#[cfg(feature = "chap3_6")]
mod chap3_6 {
use super::*;
pub struct IterMut<'a, T> {
next: Option<&'a mut Node<T>>,
}
impl<T> List<T> {
pub fn iter_mut(&self) -> IterMut<T> {
IterMut {
// 错误1: 不能对共享引用调用需要可变引用的 self.head.as_mut()
next: self.head.as_mut().map::<&mut Node<T>, _>(|node| &mut node),
}
}
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
// 错误2:map() 方法要求所有权,不能经过可变引用 self.next 获取所有权
self.next.map(|node1| {
self.next = node1.next.as_mut().map::<&mut Node<T>, _>(|node2| &mut node2);
&mut node1.elem
})
}
}
}
2.1 错误1:容易理解和修正。注意:涉及到可变引用时,强制解引用无效!!!
impl<T> List<T> {
// 错误1: 不能对共享引用调用需要可变引用的 self.head.as_mut()
// 修正:&self ---> &mut self
pub fn iter_mut(&mut self) -> IterMut<T> {
IterMut {
// 涉及到可变引用时,强制解引用无效,不能省略两级解引用运算符
// next: self.head.as_mut().map::<&mut Node<T>, _>(|node| &mut **node),
next: self.head.as_mut().map(|node| &mut **node),
}
}
}
2.2 错误2:Option 是否实现了 Copy,与被包装类型是否实现了 Copy 是一致的
// 错误2:map() 方法要求所有权,不能经过可变引用 self.next 获取所有权
self.next.map(|node1| {
- 上一节的代码也是这样写的,为什么没有出错?
- 上一节中,self.next 的类型是 Option<&’a Node
>,被包装类型&’a Node 是实现了Copy的,所以Option也是实现了Copy的。调用需要所有权的map()方法时,可以自动Copy一份,得到新值的所有权,在新值上调用map()方法。 - 这一节中,self.next 的类型是 Option<&’a mut Node
>,被包装类型&’a mut Node 没有实现Copy(独占引用是互斥的,不可能自动Copy出多个独占引用),所以Option也没有实现Copy。调用需要所有权的map()方法时,只能转移所有权,但是 self.next 是引用类型,没法转移所有权,所以编译出错。 3 修正问题:用 take() 方法从 &mut Option 获取所有权
- 上一节中,self.next 的类型是 Option<&’a Node
//=========== 3.6 IterMut ===========
//cargo test --features chap3_6 -- --nocapture iter_mut
#[cfg(feature = "chap3_6")]
mod chap3_6 {
use super::*;
pub struct IterMut<'a, T> {
next: Option<&'a mut Node<T>>,
}
impl<T> List<T> {
pub fn iter_mut(&mut self) -> IterMut<T> {
IterMut {
// 注意: 涉及独占引用时,强制解引用无效!!!
// next: self.head.as_mut().map::<&mut Node<T>, _>(|node| &mut **node),
next: self.head.as_mut().map(|node| &mut **node),
}
}
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
// 用 take() 方法取走值(获取所有权),留下None
self.next.take().map(|node1| {
// 注意: 涉及独占引用时,强制解引用无效!!!
self.next = node1.next.as_mut().map::<&mut Node<T>, _>(|node2| &mut **node2);
&mut node1.elem
})
}
}
}
- 涉及到独占引用时,强制解引用无效
- Option是否实现了Copy,与被包装类型是否实现了Copy是一致的
- 共享引用实现了Copy,独占引用没有实现Copy
- 用 take() 方法从 &mut Option 取走值(拥有所有权),留下None
- 可以从指向结构体的变量,分离出对字段的独占引用,因为已经完全分离了,没法放回来