強参照Rc<T> と弱参照Weak<T>
std::rc::Rc<T> 概要
動的な参照を実現。&
演算子による参照がコンパイル時にされるのに対して、Rc<T>
は実行時に参照を確保する。
これによってライフタイムを除去することができる。
ライフタイムの除去
参照による共有
借用チェッカーを通すために、ライフタイムを付与する必要がある
struct A<'a> { data: &'a [u8], } impl<'a> A<'a> { fn new(data: &[u8]) -> A { A { data: data, } } } // 1k bytes let big_data = (0..1000).collect::<Vec<u8>>(); let a1 = A::new(&big_data); // ビッグデータの共有1 let a2 = A::new(&big_data); // ビッグデータの共有2
Rc<T>による共有
// ライフタイムの除去 struct B { data: Rc<Vec<u8>>, } impl B { fn new(data: Rc<Vec<u8>>) -> B { B { data: data, } } } // Rcに包む let shared_data = Rc::new(big_data); let b1 = B::new(shared_data); let b2 = B::new(Rc::clone(&shared_data));
Rc::clone(&b1)
orb1.clone()
によって参照の共有を作っていく
強参照(std::rc::Rc<T>)と弱参照(std::rc::Weak<T>)
Rc::clone
を使用すると、強参照(Rc<T>
)を生成するため、互いに参照し合うと、メモリーリークを発生させる。
この場合は、Rc::downgrade
を使用することで、弱参照(Weak<T>
)を生成する。
let p = Parent::new(); let p = Rc::new(p); // 弱参照でparentと結ぶ let c1 = Child::new(Rc::downgrade(&p), 1); let c2 = Child::new(Rc::downgrade(&p), 2); let c3 = Child::new(Rc::downgrade(&p), 3); println!("{}", Rc::strong_count(&p)); // 1 // 強参照でchildを渡す p.add_child(Rc::new(c1)); p.add_child(Rc::new(c2)); p.add_child(Rc::new(c3));