cat src/main.rs use std::rc::Rc; struct Owner { name: String, // ...other fields } struct Gadget { id: i32, owner: Rc<Owner>, // ...other fields } fn main() { let gadget_owner: Rc<Owner> = Rc::new( //堆分配Owner, 产生一个Rc<Owner>计数 Owner { name: "Gadget Man".to_string(), } ); //现在有一个Owner,在堆中,一个Rc<Owner>, 指针 let gadget1 = Gadget { id: 1, owner: Rc::clone(&gadget_owner), //获得一个指向堆中Owner的Rc<Owner>,计数加一 }; let gadget2 = Gadget { id: 2, owner: Rc::clone(&gadget_owner), //获得指针,计数加一 }; //现在有一个Owner, 三个Rc<Owner> drop(gadget_owner); //std::mem::drop,销毁一个Rc<Owner>,内存Owner还在 //剩余两个Rc<Owner>仍然指向Owner println!("Gadget {} owned by {}", gadget1.id, gadget1.owner.name); println!("Gadget {} owned by {}", gadget2.id, gadget2.owner.name); }
[root@bogon Rc]# cargo build Compiling own v0.1.0 (/data2/rust/Rc) Finished dev [unoptimized + debuginfo] target(s) in 0.56s [root@bogon Rc]# cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.01s Running `target/debug/own` Gadget 1 owned by Gadget Man Gadget 2 owned by Gadget Man
Rc<T>, 引用计数器,用来记录一个值是否被使用,如果计数为零可清除。适用于堆中数据需要被程序多部分使用,但编译时不能确定谁最后完成。
本质上,Rc<T>类似于这样一个东西:
//pseudo code
{
let a = some_big_data;
let b = &a; //counter = 1
let c = &a; //counter = 2
{
let d = &a; //counter = 3
} //counter = 2
let d = &a; //counter = 3
} //counter = 0
Rc<T>通过clone来获得新的Rc<T>指针,增加计数
use std::rc::Rc;
let foo = Rc::new(vec![1.0, 2.0, 3.0]); //产生一个不可变的引用
// 等价
let a = foo.clone(); //trait,不同于其他类型的clone that is deep copy
let b = Rc::clone(&foo);
//至此三个Rc<Vec>指向同一个堆中的Vec
//Rc<T>.clone == Rc::clone(&T), 但Rc::clone(&T)为惯用语法,
文档例子
use std::rc::Rc;
struct Owner {
name: String,
// ...other fields
}
struct Gadget {
id: i32,
owner: Rc<Owner>,
// ...other fields
}
fn main() {
let gadget_owner: Rc<Owner> = Rc::new( //堆分配Owner, 产生一个Rc<Owner>计数
Owner {
name: "Gadget Man".to_string(),
}
); //现在有一个Owner,在堆中,一个Rc<Owner>, 指针
let gadget1 = Gadget {
id: 1,
owner: Rc::clone(&gadget_owner), //获得一个指向堆中Owner的Rc<Owner>,计数加一
};
let gadget2 = Gadget {
id: 2,
owner: Rc::clone(&gadget_owner), //获得指针,计数加一
}; //现在有一个Owner, 三个Rc<Owner>
drop(gadget_owner); //std::mem::drop,销毁一个Rc<Owner>,内存Owner还在
//剩余两个Rc<Owner>仍然指向Owner
println!("Gadget {} owned by {}", gadget1.id, gadget1.owner.name);
println!("Gadget {} owned by {}", gadget2.id, gadget2.owner.name);
} //gadget1, gadget2出局,Rc<Owner>归零,Owner内存释放
Cons list例子
//使用Box<T>, 只允许单个所有者
enum List {
Cons(i32, Box<List>),
Nil,
}
use List::{Cons, Nil};
fn main() { //不能编译
let a = Cons(5, //a在栈,Box在栈指向堆中Cons(10)
Box::new(Cons(10,
Box::new(Nil)))); //Cons(5, Box) -> Cons(10, Box) -> Nil
let b = Cons(3, Box::new(a)); //Cons(3, Box) -> a, 夺权。Box在堆中分配内存,放入a
let c = Cons(4, Box::new(a)); //Cons(4, Box) -> a,无权使用
}
//使用Rc<T>, 允许多个拥有者
enum List {
Cons(i32, Rc<List>),
Nil,
}
use List::{Cons, Nil};
use std::rc::Rc; //需要引入
fn main() {
let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil))))); //Cons is List
//外层Rc::New创建一个Rc<List>, Cons(5, 10)全部在堆
println!("count after creating a = {}", Rc::strong_count(&a)); //1
//pub fn strong_count(this: &Rc<T>) -> usize
let b = Cons(