2015-11-05 66 views
5

鉴于以下structimpl返回A VEC的迭代器在RefCell

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 

我怎么能够返回和使用bar s迭代器?

回答

9

你不能这样做,因为它可以让你绕过唯一性违规的运行时检查。

RefCell为您提供了一种将可变性排他性检查延迟到运行时的方法,作为交换允许通过共享引用对其保存的数据进行突变。这是使用RAII后卫来完成:可以使用共享参考RefCell获得保护对象,然后使用该保护对象访问内部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() 
    } 
} 

(尝试on playground

您不能VecRefWrapper实现IntoIterator直接因为内部Ref将被into_iter()消耗,给你基本上与你现在一样的情况。

+0

终身是如此艰难!恭喜理解并解释它。 – Moebius