Rust 智能指针
Rc 和 Arc
Rust 所有权机制要求一个值只能有一个所有者,在大多数情况下,都没有问题,但是考虑以下情况:
- 在图数据结构中,多个边可能会拥有同一个节点,该节点直到没有边指向它时,才应该被释放清理
- 在多线程中,多个线程可能会持有同一个数据,但是你受限于 Rust 的安全机制,无法同时获取该数据的可变引用
Rc<T>
当我们希望在堆上分配一个对象供程序的多个部分使用且无法确定哪个部分最后一个结束时,就可以使用 Rc 成为数据值的所有者,例如之前提到的多线程场景就非常适合。
例如:
rust
use std::rc::Rc;
fn main() {
let a = Rc::new(String::from("hello, world"));
let b = Rc::clone(&a);
assert_eq!(2, Rc::strong_count(&a));
assert_eq!(Rc::strong_count(&a), Rc::strong_count(&b))
}这里的 clone 仅仅复制了智能指针并增加了引用计数,并没有克隆底层数据。比起 a.clone() 更推荐使用 Rc::clone()。
Rc<T> 是指向底层数据的不可变引用,因此无法通过它修改数据。但实际开发中我们往往需要对数据进行修改,需要配合其他数据类型一起使用,例如 RefCell<T> 和 Mutex<T>。在多线程场景下,Arc 经常和 Mutex 一起使用。
Rc 不能在多线程场景中使用,因为它没有实现 Send trait.。更深层的原因是,Rc<T> 的引用计数并没有使用任何并发原语。
Arc
Arc 与 Rc 使用基本相同,只不过 Arc 在多线程场景使用且伴随性能损耗。