1 IterMut 很难搞定

从原理上说,Iter 与 IterMut 是完全相同的,但是 IterMut 很难搞定。

1.1 原始定义

  1. impl<'a, T> Iterator for Iter<'a, T> {
  2. type Item = &'a T;
  3. fn next(&mut self) -> Option<Self::Item> { /* stuff */ }
  4. }

1.2 去掉语法糖(生命周期注解省略)

  1. impl<'a, T> Iterator for Iter<'a, T> {
  2. type Item = &'a T;
  3. fn next<'b>(&'b mut self) -> Option<&'a T> { /* stuff */ }
  4. // 这就是说:输出(返回值)的生命周期,与输入的生命周期无关!!!
  5. // 所以,可以省略输入参数的生命周期注解
  6. }

1.3 可以不断调用next()方法

  1. let mut list = List::new();
  2. list.push(1); list.push(2); list.push(3);
  3. let mut iter = list.iter();
  4. let x = iter.next().unwrap();
  5. let y = iter.next().unwrap();
  6. let z = iter.next().unwrap();
  • 对共享引用没有问题:可以同时拥有很多共享引用
  • 对独占(可变)引用不可行:独占引用是不相容的。结果就是:使用安全代码实现IterMut有些难。

    2 首次尝试:完全复制Iter的代码,但是把所有共享引用的地方,改成独占引用

  1. //=========== 3.6 IterMut ===========
  2. //cargo test --features chap3_6 -- --nocapture iter_mut
  3. #[cfg(feature = "chap3_6")]
  4. mod chap3_6 {
  5. use super::*;
  6. pub struct IterMut<'a, T> {
  7. next: Option<&'a mut Node<T>>,
  8. }
  9. impl<T> List<T> {
  10. pub fn iter_mut(&self) -> IterMut<T> {
  11. IterMut {
  12. // 错误1: 不能对共享引用调用需要可变引用的 self.head.as_mut()
  13. next: self.head.as_mut().map::<&mut Node<T>, _>(|node| &mut node),
  14. }
  15. }
  16. }
  17. impl<'a, T> Iterator for IterMut<'a, T> {
  18. type Item = &'a mut T;
  19. fn next(&mut self) -> Option<Self::Item> {
  20. // 错误2:map() 方法要求所有权,不能经过可变引用 self.next 获取所有权
  21. self.next.map(|node1| {
  22. self.next = node1.next.as_mut().map::<&mut Node<T>, _>(|node2| &mut node2);
  23. &mut node1.elem
  24. })
  25. }
  26. }
  27. }

2.1 错误1:容易理解和修正。注意:涉及到可变引用时,强制解引用无效!!!

  1. impl<T> List<T> {
  2. // 错误1: 不能对共享引用调用需要可变引用的 self.head.as_mut()
  3. // 修正:&self ---> &mut self
  4. pub fn iter_mut(&mut self) -> IterMut<T> {
  5. IterMut {
  6. // 涉及到可变引用时,强制解引用无效,不能省略两级解引用运算符
  7. // next: self.head.as_mut().map::<&mut Node<T>, _>(|node| &mut **node),
  8. next: self.head.as_mut().map(|node| &mut **node),
  9. }
  10. }
  11. }

2.2 错误2:Option 是否实现了 Copy,与被包装类型是否实现了 Copy 是一致的

  1. // 错误2:map() 方法要求所有权,不能经过可变引用 self.next 获取所有权
  2. 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 获取所有权

  1. //=========== 3.6 IterMut ===========
  2. //cargo test --features chap3_6 -- --nocapture iter_mut
  3. #[cfg(feature = "chap3_6")]
  4. mod chap3_6 {
  5. use super::*;
  6. pub struct IterMut<'a, T> {
  7. next: Option<&'a mut Node<T>>,
  8. }
  9. impl<T> List<T> {
  10. pub fn iter_mut(&mut self) -> IterMut<T> {
  11. IterMut {
  12. // 注意: 涉及独占引用时,强制解引用无效!!!
  13. // next: self.head.as_mut().map::<&mut Node<T>, _>(|node| &mut **node),
  14. next: self.head.as_mut().map(|node| &mut **node),
  15. }
  16. }
  17. }
  18. impl<'a, T> Iterator for IterMut<'a, T> {
  19. type Item = &'a mut T;
  20. fn next(&mut self) -> Option<Self::Item> {
  21. // 用 take() 方法取走值(获取所有权),留下None
  22. self.next.take().map(|node1| {
  23. // 注意: 涉及独占引用时,强制解引用无效!!!
  24. self.next = node1.next.as_mut().map::<&mut Node<T>, _>(|node2| &mut **node2);
  25. &mut node1.elem
  26. })
  27. }
  28. }
  29. }
  • 涉及到独占引用时,强制解引用无效
  • Option是否实现了Copy,与被包装类型是否实现了Copy是一致的
  • 共享引用实现了Copy,独占引用没有实现Copy
  • 用 take() 方法从 &mut Option 取走值(拥有所有权),留下None
  • 可以从指向结构体的变量,分离出对字段的独占引用,因为已经完全分离了,没法放回来