首页 文章

借用vs变异借用生命中的奇怪失败

提问于
浏览
5

在尝试实现一个迭代器,它产生可变的refs到链表的元素时,我偶然发现了一个奇怪的问题 .

这很好用:

impl<'a, T> Iterator<&'a T> for LinkedListIterator<'a, T>{
    fn next(&mut self) -> Option<&'a T> {
        match self.current {
            &Cell(ref x, ref xs) => {self.current = &**xs; Some(x)},
            &End                 => None
        }
    }
}

但这不起作用;编译器说 self 的生命周期太短,无法保证其内容可以安全地重新借用:

impl<'a, T> Iterator<&'a mut T> for LinkedListMutIterator<'a, T>{
    fn next(&mut self) -> Option<&'a mut T> {
        match self.current {
            &Cell(ref mut x, ref mut xs) => {self.current = &mut **xs; Some(x)},
            &End                         => None
        }
    }
}

我希望这两个例子都可以工作,或者两者都没有,但是我无法理解借用可变因素和不可变因素会如何影响编译器检查生命周期的方式 . 当然,如果有些东西足够长,可以安全地借用,它的寿命足够长,可以安全地可靠地借用?

编辑:这是两个迭代器的定义:

pub struct LinkedListIterator<'a, T> 
    current: &'a LinkedList<T>
}

pub struct LinkedListMutIterator<'a, T> {
    current: &'a mut LinkedList<T>
}

LinkedLisk:

#[deriving(Eq, Clone)]
pub enum LinkedList<T> {
    Cell(T, ~LinkedList<T>),
    End
}

有关该文件的完整视图,请参阅https://github.com/TisButMe/rust-algo/blob/mut_iter/LinkedList/linked_list.rs

1 回答

  • 2

    请注意,对于代码的两个变体位,您已经省略了 LinkedListMutIterator 的定义,这可能与重现和剖析问题的任何实际尝试相关 .


    所以,我会试着猜测发生了什么 .

    这里的编译器错误消息可能会误导您;除了 self 的生命周期之外还有其他因素可能与此相关 .

    特别是我怀疑借用检查器是在抱怨,因为它试图确保你没有创建多个可变借用的别名相同的状态 .

    • 对同一个州有多个不可变借词是合理的......

    • ...但你不能有多个可变借用到同一个状态(因为我们想要确保如果你有一个状态的 &mut 引用,那么该引用是改变状态的唯一方法) .

相关问题