给定以下structimpl

use std::slice::Iter;
use std::cell::RefCell;

struct Foo {
    bar: RefCell<Vec<u32>>,
}

impl Foo {
    pub fn iter(&self) -> Iter<u32> {
        self.bar.borrow().iter()
    }
}

fn main() {}

我收到一条关于终生问题的错误消息:
error: borrowed value does not live long enough
  --> src/main.rs:9:9
   |
9  |         self.bar.borrow().iter()
   |         ^^^^^^^^^^^^^^^^^ does not live long enough
10 |     }
   |     - temporary value only lives until here
   |
note: borrowed value must be valid for the anonymous lifetime #1 defined on the body at 8:36...
  --> src/main.rs:8:37
   |
8  |       pub fn iter(&self) -> Iter<u32> {
   |  _____________________________________^ starting here...
9  | |         self.bar.borrow().iter()
10 | |     }
   | |_____^ ...ending here

如何返回并使用bars迭代器?

最佳答案

您不能这样做,因为这样可以避免运行时检查唯一性冲突。
RefCell为您提供了一种将可变排他性检查“延迟”到运行时的方法,从而允许通过共享引用对其内部保存的数据进行变异。这是使用RAII guards完成的:您可以使用RefCell的共享引用获取guard对象,然后使用此guard对象访问RefCell中的数据:

&'a RefCell<T>        -> Ref<'a, T> (with borrow) or RefMut<'a, T> (with borrow_mut)
&'b Ref<'a, T>        -> &'b T
&'b mut RefMut<'a, T> -> &'b mut T

这里的关键点是'b'a不同,后者允许获得&mut T引用,而不需要对&mut进行RefCell引用。但是,这些引用将链接到守卫,并且不能比守卫活得长。这是有意完成的:RefRefMut析构函数在其RefCell中切换各种标志,以强制可变性检查,并在这些检查失败时强制borrow()borrow_mut()惊慌。
您可以做的最简单的事情是在Ref周围返回一个包装器,对它的引用将实现IntoIterator
use std::cell::Ref;

struct VecRefWrapper<'a, T: 'a> {
    r: Ref<'a, Vec<T>>
}

impl<'a, 'b: 'a, T: 'a> IntoIterator for &'b VecRefWrapper<'a, T> {
    type IntoIter = Iter<'a, T>;
    type Item = &'a T;

    fn into_iter(self) -> Iter<'a, T> {
        self.r.iter()
    }
}

(试试看)
您不能直接为IntoIterator实现VecRefWrapper,因为这样内部的Ref将被into_iter()消耗,这与您现在所处的情况基本相同。

09-15 11:50