35人参与 • 2025-09-24 • rust
智能指针是rust中管理内存和所有权的核心工具,通过封装指针并添加元数据(如引用计数)来实现安全的内存管理。以下是主要类型及其原理、使用场景和示例:

fn main() {
let b = box::new(5); // 在堆上存储整数5
println!("b = {}", b); // 输出: b = 5
} // 离开作用域,堆内存自动释放
use std::rc::rc;
fn main() {
let a = rc::new(10);
let b = rc::clone(&a); // 引用计数+1
println!("count: {}", rc::strong_count(&a)); // 输出: count: 2
} // 离开作用域,计数归零,内存释放
borrow()和borrow_mut()访问。use std::cell::refcell;
fn main() {
let c = refcell::new(42);
*c.borrow_mut() += 1; // 运行时借用检查
println!("c = {}", c.borrow()); // 输出: c = 43
}
rc<t>,但使用原子操作保证线程安全。性能略低于rc。mutex)。use std::sync::arc;
use std::thread;
fn main() {
let val = arc::new(100);
let handle = thread::spawn(move || {
println!("thread: {}", val); // 安全共享
});
handle.join().unwrap();
}
mutex<t>:互斥锁,一次仅允许一个线程访问数据。
use std::sync::{arc, mutex};
use std::thread;
fn main() {
let counter = arc::new(mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
let c = arc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = c.lock().unwrap();
*num += 1; // 修改受保护数据
});
handles.push(handle);
}
for handle in handles { handle.join().unwrap(); }
println!("result: {}", *counter.lock().unwrap()); // 输出: result: 10
}
rwlock<t>:读写锁,允许多个读取或单个写入。use std::sync::rwlock;
let lock = rwlock::new(5);
{
let r1 = lock.read().unwrap(); // 多个读取并发
let r2 = lock.read().unwrap();
}
{
let mut w = lock.write().unwrap(); // 独占写入
*w += 1;
}
use std::rc::{rc, weak};
use std::cell::refcell;
// 定义节点结构
struct node {
value: i32,
parent: refcell<weak<node>>, // 使用 weak 避免循环引用
children: refcell<vec<rc<node>>>, // 子节点使用 rc
}
fn main() {
// 创建叶子节点
let leaf = rc::new(node {
value: 3,
parent: refcell::new(weak::new()),
children: refcell::new(vec![]),
});
// 创建分支节点,并设置 leaf 为其子节点
let branch = rc::new(node {
value: 5,
parent: refcell::new(weak::new()),
children: refcell::new(vec![rc::clone(&leaf)]),
});
// 设置 leaf 的父节点为 branch(使用 downgrade 创建弱引用)
*leaf.parent.borrow_mut() = rc::downgrade(&branch);
// 尝试升级 leaf 的父节点
if let some(parent) = leaf.parent.borrow().upgrade() {
println!("leaf 的父节点值: {}", parent.value); // 输出: leaf 的父节点值: 5
} else {
println!("父节点已被释放");
}
// 当 branch 被丢弃时,leaf 的 parent 升级会失败
}
rc<refcell<t>>:单线程内共享可变数据。
let shared_data = rc::new(refcell::new(vec![1, 2])); shared_data.borrow_mut().push(3); // 修改共享数据
arc<mutex<t>>:多线程共享可变数据(最常见组合)。let data = arc::new(mutex::new(0)); // 多线程修改数据(见上文mutex示例)
| 类型 | 线程安全 | 可变性 | 适用场景 |
|---|---|---|---|
| box<t> | ❌ | 所有权唯一 | 堆分配、递归类型 |
| rc<t> | ❌ | 不可变共享 | 单线程共享只读数据 |
| refcell<t> | ❌ | 内部可变 | 单线程运行时借用检查 |
| arc<t> | ✅ | 不可变共享 | 多线程共享只读数据 |
| mutex<t> | ✅ | 线程安全可变 | 多线程互斥修改数据 |
| rwlock<t> | ✅ | 读写分离 | 读多写少场景 |
以下是一个复杂的 rust 智能指针示例,结合了 rc、refcell 和自定义智能指针,模拟图形渲染场景中的资源管理:
use std::rc::{rc, weak};
use std::cell::refcell;
use std::ops::deref;
// 自定义智能指针:带引用计数的纹理资源
struct texture {
id: u32,
data: vec<u8>,
}
impl texture {
fn new(id: u32, size: usize) -> self {
texture {
id,
data: vec![0; size],
}
}
}
// 自定义智能指针:texturehandle
struct texturehandle(rc<texture>);
impl texturehandle {
fn new(texture: texture) -> self {
texturehandle(rc::new(texture))
}
fn get_id(&self) -> u32 {
self.0.id
}
}
impl deref for texturehandle {
type target = texture;
fn deref(&self) -> &self::target {
&self.0
}
}
// 场景节点:支持父子关系
struct scenenode {
name: string,
texture: option<texturehandle>,
children: refcell<vec<rc<refcell<scenenode>>>>,
parent: refcell<weak<refcell<scenenode>>>,
}
impl scenenode {
fn new(name: &str) -> rc<refcell<self>> {
rc::new(refcell::new(scenenode {
name: name.to_string(),
texture: none,
children: refcell::new(vec::new()),
parent: refcell::new(weak::new()),
}))
}
fn add_child(parent: &rc<refcell<scenenode>>, child: &rc<refcell<scenenode>>) {
child.borrow_mut().parent.replace(rc::downgrade(parent));
parent.borrow_mut().children.borrow_mut().push(rc::clone(child));
}
fn set_texture(&mut self, texture: texturehandle) {
self.texture = some(texture);
}
fn print_tree(&self, depth: usize) {
let indent = " ".repeat(depth);
println!("{}{}", indent, self.name);
if let some(tex) = &self.texture {
println!("{}texture id: {}", indent, tex.get_id());
}
for child in self.children.borrow().iter() {
child.borrow().print_tree(depth + 1);
}
}
}
fn main() {
// 创建共享纹理资源
let shared_texture = texturehandle::new(texture::new(101, 1024));
// 创建场景节点
let root = scenenode::new("root");
let camera = scenenode::new("camera");
let mesh1 = scenenode::new("mesh1");
let mesh2 = scenenode::new("mesh2");
// 设置纹理
{
let mut root_mut = root.borrow_mut();
root_mut.set_texture(shared_texture);
}
// 构建场景层级
scenenode::add_child(&root, &camera);
scenenode::add_child(&root, &mesh1);
scenenode::add_child(&mesh1, &mesh2);
// 打印场景树
root.borrow().print_tree(0);
// 验证引用计数
println!("\nreference counts:");
println!("root strong: {}", rc::strong_count(&root));
println!("root weak: {}", rc::weak_count(&root));
}
示例解析:
自定义智能指针 texturehandle
rc<texture> 实现资源共享deref 获得透明访问场景图管理 scenenode
rc<refcell<scenenode>> 实现共享所有权和内部可变性refcell<vec<rc<...>>> 实现运行时可变借用refcell<weak<...>> 避免循环引用资源共享机制
texturehandle 共享rc 共享所有权weak 引用打破循环依赖输出示例:
root
texture id: 101
camera
mesh1
mesh2
reference counts:
root strong: 1
root weak: 2
ps g:\learning\rust\ttt>

关键特性:
refcell 修改不可变引用weak 指针避免内存泄漏deref 实现直接访问refcell 在运行时验证借用规则到此这篇关于rust 智能指针的使用详解的文章就介绍到这了,更多相关rust 智能指针内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论