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 selfpub 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() 方法取走值(获取所有权),留下Noneself.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
- 可以从指向结构体的变量,分离出对字段的独占引用,因为已经完全分离了,没法放回来
