当前位置: 首页 > news >正文

Rc:引用计数与共享所有权

在 Rust 的严苛所有权法则下,一个值通常只有一个所有者。然而,现实开发中(如图形结构、多路搜索树或 UI 框架)经常需要共享所有权Rc<T>(Reference Counted)正是为此而生。

1. 什么是 Rc

Rc<T> 是一个只读的、具有引用计数的智能指针。它允许你在堆上分配内存,并让多个变量共同拥有这块内存的所有权。只有当最后一个所有者销毁时,堆上的内存才会被释放。

核心原则Rc<T> 仅适用于单线程场景。如果需要跨线程共享,请使用 Arc<T>

2. 内存布局剖析

当你创建一个 Rc::new(data) 时,Rust 会在堆上分配一个特殊的结构体 RcBox<T>

Rc 内存布局

  • 栈上(Stack)Rc<T> 本身是一个指针,指向堆上的 RcBox
  • 堆上(Heap)RcBox 包含三个部分:
    1. Strong Count:强引用计数。决定了值的生命周期。
    2. Weak Count:弱引用计数。辅助处理循环引用(本文暂不深入探讨)。
    3. Value:实际存储的数据 T

3. 共享所有权:引用计数的变化

使用 Rc::clone(&rc) 不会深拷贝堆上的数据,而只是在栈上创建一个新的指针,并增加堆上的强引用计数。

地道写法提示:在 Rust 中,我们倾向于写 Rc::clone(&rc) 而不是 rc.clone()。虽然两者效果相同,但前者能一眼看出这只是一个增加计数的“廉价”克隆,而不是昂贵的数据深拷贝。

共享所有权

use std::rc::Rc;fn main() {let rc1 = Rc::new(String::from("Shared Data"));println!("Count after rc1: {}", Rc::strong_count(&rc1)); // 1{// 显式调用 Rc::clone,语义更清晰let rc2 = Rc::clone(&rc1); println!("Count after rc2: {}", Rc::strong_count(&rc1)); // 2} // rc2 离开作用域,计数减 1println!("Count after rc2 dropped: {}", Rc::strong_count(&rc1)); // 1
}

4. 痛点:Rc 是不可变的

Rc<T> 赋予了你“共享”的能力,但它通过 Deref 提供的引用是只读的。这是为了防止多个所有者同时修改数据导致的数据竞争(即使在单线程下,多处可变借用也是不安全的)。

如果你需要修改 Rc 内部的数据,通常需要配合 内部可变性(Interior Mutability) 模式,这超出了本文的讨论范围。

5. 致命陷阱:循环引用 (Reference Cycles)

虽然 Rc 能自动管理内存,但它无法处理循环引用。如果两个 Rc 互相指向对方,它们的引用计数将永远不会归零,导致内存泄漏。

引用循环

6. 避坑指南

  1. 不要在多线程中使用Rc<T> 没有实现 SendSync trait。在多线程环境下,引用计数的加减操作不是原子的,会导致计数错误。
  2. 克隆 vs 拷贝:虽然 Rc::clone 很轻量,但它依然涉及堆内存访问和计数操作。如果只是在局部函数中使用,直接传递 &T 通常更高效。

7. 最佳实践

只有在“无法确定谁是最终所有者”或“数据确实需要被多个不相关的结构共享”时,才使用 Rc<T>

http://www.jsqmd.com/news/330535/

相关文章:

  • 网络安全入门基础-常用工具安装及使用(下)
  • P10801 [CEOI 2024] 海战
  • 三菱Q系列PLC大型自动化生产线程序案例分享
  • 探索工频UPS逆变器控制板的宝藏世界
  • FastAPI系列(18):ORM查询操作
  • 在光学与电磁领域中的多元技术探索与实践
  • 电动汽车集群优化:Matlab 与 Yalmip 的奇妙结合
  • 2026降AI率指南:10款论文降ai工具红黑榜!亲测哪个免费降ai率工具不“智障”?
  • MATLAB程序实现排列熵算法:含详细注释版本
  • 使用 Rust 与 Tokio 构建高性能异步微服务:从零到生产部署实战指南
  • devtest-20260201 - devtest
  • 单相七电平级联逆变器开环仿真之旅(MATLAB/Simulink 实现)
  • Day26焦点事件
  • Go语言并发模式详解:从Goroutine到Channel最佳实践
  • 污水处理项目:西门子S7 - 300PLC与TP900触摸屏仿真T125实战
  • Redis深度优化:如何通过数据结构设计提升缓存命中率
  • 2026年1月靠谱OMO模式数字经济电商平台推荐排行榜,数字化电子商务,OMO模式数字经济电商平台排行榜单
  • 基于Java技术的大学生跑腿系统的设计与开发 开题报告
  • Matlab法诺共振拟合与Q因子计算:探索微观世界的奇妙工具
  • 探索PEMFC质子交换膜燃料电池模型:从密歇根大学模型到自主搭建
  • 部署安装 K8s 为什么要关闭 swap 分区?
  • AT_agc040_c Neither AB nor BA
  • AI原生应用领域推理能力的实时性优化
  • 新能源锂电池项目欧姆龙 NJ 程序实战分享
  • Go语言并发模式解析:channel与goroutine最佳实践
  • Clawdbot安装教程:从零开始到接入飞书
  • 基于MATLAB与CNN的语音信号分类探索
  • 老年人能力评估系统开发Day8
  • MATLAB代码:考虑电动汽车有序充放电的机组组合和最优潮流 关键词:电动汽车 MILP 最优...
  • GPUHammer:首个针对NVIDIA GPU的Rowhammer攻击专业的技术