让我们创建共享第三个列表所有权的两个列表。
在上图中,B和C是与第三个列表的所有权共享的两个列表,a。
让我们使用Box <T>类型实现上述方案。
enum List { Cons(i32, Box<List>), Nil, } use List::{Cons,Nil}; fn main() { let a = Cons(10, Box::new(Cons(15,Box::new(Nil)))); let b = Cons(2, Box::new(a)); let c = Cons(1, Box::new(a)); }
输出:
在上面的示例中,cons变体包含类型为i32的数据和Box <T>指向列表的数据。我们创建列表"b",并将"a"的所有权移至"b"列表。然后,我们尝试将"a"列表移动到"c"列表,但是由于"a"列表已经移动到"b"列表,因此无法移动列表。
我们可以通过更改cons变体的定义来克服此问题。现在,cons变体由它们保存的数据和指向List的Rc <T>组成。
让我们看看一个简单的例子:
enum List { Cons(i32, Rc), Nil, } use List::{Cons,Nil}; use std::rc::Rc; fn main() { let a = Rc::new(Cons(10, Rc::new(Cons(15,Rc::new(Nil))))); let b = Cons(2, Rc::clone(&a)); let c = Cons(1, Rc::clone(&a)); }
在上面的示例中,我们需要添加use语句以将Rc <T>纳入范围。代替获取a的所有权,我们将克隆a持有的Rc <T>列表,因此现在将引用的数量从一增加到两个,a和b共享该Rc <列表>。创建c List时,我们将再次克隆Rc <List>,因此将引用从两个增加到三个。
现在,我们将看到列表超出范围时Rc <T>如何增加或减少引用计数。
让我们看看一个简单的例子:
enum List { Cons(i32, Rc<List>), Nil, } use List::{Cons,Nil}; use std::rc::Rc; fn main() { let a = Rc::new(Cons(10, Rc::new(Cons(15,Rc::new(Nil))))); println!("Reference count after creating a List : {}", Rc::strong_count(&a)); let b = Cons(2, Rc::clone(&a)); println!("Reference count after creating b List : {}", Rc::strong_count(&a)); { let c = Cons(1, Rc::clone(&a)); println!("Reference count after creating c List : {}",Rc::strong_count(&a)); } println!("Reference count when c goes out of the scope : {}",Rc::strong_count(&a)); }
输出:
Reference count after creating a List : 1 Reference count after creating b List : 2 Reference count after creating c List : 3 Reference count when c goes out of the scope : 2
在上面的示例中,我们通过调用Rc ::strong_count函数来打印参考计数。 Rc <List>中a的初始引用计数为1,当我们调用clone时,引用计数增加1。如果变量超出范围,则引用计数减少1。因此,我们可以说当Rc <T> 值超出范围时,Drop trait会自动减少参考计数。
祝学习愉快!(内容编辑有误?请选中要编辑内容 -> 右键 -> 修改 -> 提交!)