IB-Rust-智能指针2
课程概述
Rc<T>RefCell<T>Weak<T>
Rc<T> 引用计数指针
什么是 Rc<T>?
- Rc 是 Reference Counted(引用计数) 的缩写
- 允许多所有者的共享所有权模型
举例说明
使用 Box<T> 定义 cons list 的例子。这一次,我们希望创建两个共享第三个列表所有权的列表
尝试使用 Box<T> 定义的 List:
1 | use crate::List::{Cons, Nil}; |
使用 Rc<T> 实现
1 | use crate::List::{Cons, Nil}; |
RefCell<T>
什么是RefCell<T>?
RefCell<T> 是一个智能指针类型,允许在编译时无法确定的情况下,在运行时进行借用检查
主要特征
- 内部可变性:
RefCell<T>允许你在其拥有的T内部进行修改,即使RefCell本身是不可变的。这是通过在运行时进行借用检查实现的
- 运行时借用检查:
RefCell使用动态借用检查,确保在运行时遵循 Rust 的借用规则,即在任何时刻,RefCell只能有一个可变借用或多个不可变借用,但不能同时存在
borrow和borrow_mut方法:RefCell提供了两个方法来获取对内部数据的借用:borrow():获取不可变借用(Ref<T>),可以同时有多个borrow_mut():获取可变借用(RefMut<T>),在同一时间只能有一个
关键点
- 借用规则:
RefCell在运行时检查借用规则,以防止数据竞争和未定义行为。编译器不进行这些检查,而是依赖RefCell在运行时进行
- 运行时开销:
- 因为
RefCell需要在运行时检查借用规则,所以它会引入一定的性能开销。这在需要在编译时确定所有借用规则的场景中不可替代
- 因为
- 错误处理:
- 如果违反了借用规则(例如,尝试同时获取多个可变借用),
RefCell会在运行时引发 panic
- 如果违反了借用规则(例如,尝试同时获取多个可变借用),
使用场景
- 数据结构:
- 在需要可变性但又受限于 Rust 的所有权系统时,
RefCell允许在数据结构中使用内部可变性。例如,实现需要共享但修改的数据结构(如图、树)
- 在需要可变性但又受限于 Rust 的所有权系统时,
- 单线程环境:
RefCell主要用于单线程环境。如果你需要在多线程环境中处理内部可变性,应该使用 Mutex 或 RwLock 这类类型。
引用循环与内存泄漏
引用计数(Rc<T>)和原子引用计数(Arc<T>)可以让多个所有者共享同一个数据。然而,这种共享机制如果不当使用,可能会导致引用循环(reference cycle),从而造成内存泄漏
例子
1 | use std::rc::Rc; |
Weak<T> 弱引用
Weak<T> 的特点
- 非所有权引用:
Weak<T>并不拥有数据的所有权,因此它不会影响Rc<T>的引用计数 - 不会引发内存泄漏: 由于
Weak<T>不增加引用计数,可以避免引用循环问题,从而避免内存泄漏 - 必须升级:
Weak<T>是一个非所有权引用,因此在使用数据之前,需要通过upgrade()方法将其升级为Rc<T>。如果数据已经被释放,upgrade()会返回None
解决循环引用
1 | use std::cell::RefCell; |
强引用与弱引用的主要区别
所有权:
- 强引用 (
Rc<T>): 持有数据的所有权,保证数据在作用域内不会被释放。 - 弱引用 (
Weak<T>): 不持有数据的所有权,不影响数据的生命周期。
- 强引用 (
引用计数:
- 强引用: 增加引用计数,数据被多个所有者共享。
- 弱引用: 不增加引用计数,不干扰
Rc<T>的生命周期管理。
内存管理:
- 强引用: 只有当所有强引用都被丢弃时,数据才会被释放。
- 弱引用: 只能通过升级 (
upgrade()) 来访问数据,如果数据已经被释放,则升级会失败。
适用场景:
- 强引用: 当你希望共享数据并确保数据在至少一个强引用存在时不会被释放。
- 弱引用: 当你需要避免引用循环或只需要偶尔访问数据,不想持有其所有权时。
课后作业
任务: 实现一个简单的社交网络系统,包含用户和朋友关系。使用 Rc<T>, RefCell<T>, Weak<T> 来处理用户和朋友之间的关系,并避免循环引用导致的内存泄漏
要求:
- 用户结构: 每个用户拥有一个名字和一个朋友列表。
- 添加朋友: 支持在两个用户之间建立朋友关系。
- 展示朋友关系: 能够展示每个用户的朋友列表。
- 循环引用: 处理用户之间的双向引用,确保不产生循环引用。
1 | use std::cell::RefCell; |
- Title: IB-Rust-智能指针2
- Author: Gabrielle
- Created at : 2025-06-09 13:08:47
- Updated at : 2025-06-10 21:55:47
- Link: https://zoella-w.github.io/2025/06/09/77-IB-Rust-智能指针2/
- License: This work is licensed under CC BY-NC-SA 4.0.