Box<T> | 概念:简单的智能指针 用于在堆上分配数据 比喻:想象你有一件很重的东西(比如一大本书),你不想一直拿着它。所以,你把它放在一个盒子里(Box),然后只拿着盒子的标签(指针)。这样,你只需要记得标签的位置,就能找到那件东西。 用途: 1.当你需要在堆上分配数据,而不是在栈上时 //堆和栈的区别: 栈:操作系统自动管理 存储函数的局部变量。 就像一摞盘子,用完就放回 堆:程序员手动管理 存储程序运行动态分配的内存 如对象 数组。 就像一个仓库, 东西可以随意存放,但需要自己收拾 2.当类型的实际大小只有在运行时才能确定 3.想要将大对象的所有权转移给函数,但又不想复制数据 |
Rc<T> | 概念:引用计数,允许多个所有者共享同一数据 比喻:假设你和你的朋友都想读同一本书,但是你们不想每个人都购买,于是你们决定一起买一本。每个人都有个借阅卡Rc<T>,当你或者你朋友想读书时, 拿出借阅卡,当所有人都读完并且还借阅卡后,这书才会被处理掉 用途 1.在单线程环境中共享数据 2.希望多个所有者可以访问同一个数据,但不需要同时修改它 例子 use std::rc::Rc; let a = Rc::new(5); let b = Rc::clone(&a); println!("a = {}, b = {}", a, b); |
Arc<T> | 概念:是Rc<T>的线程安全版本,全程是Atomic Reference Counting 它与Rc<T>类似,但可以安全的多线程间共享数据 比喻:假设你和你朋友不仅想在同一本书上做笔记,还想同时做这件事情。为了安全起见,你们决定使用一种特殊的借阅卡Arc<T> 这种卡可以确保多人使用 也不会出错 用途 1.需要在多个线程中共享数据 2.希望多个线程可以安全地访问同一个数据 例子 use std::sync::Arc; use std::thread; let a = Arc::new(5); let b = Arc::clone(&a) let handle = thread::spawn(move || { println!("b in thread = {}",b ) }) |
RefCell<T> | 概念:提供运行检查时所有规则;通常情况下rust所有权规则是在编译时检查的,但是RefCell<T>允许你在运行时改变数据,即使在不可变引用存在的情况下 比喻:假设你有一本图书馆的书,图书馆规定你不能在书上做笔记。但是,你发现了一个秘密房间(RefCell<T>),在这个房间里,你可以自由地在书上做笔记,只要没有人发现。如果有人发现了,程序会报错。 用途: 1.当你需要在不可变引用存在的情况下修改数据 2.当你需要在运行时动态地检查借用规则 例子: use std::cell::RefCall; let c = RefCell::new(5); { let mut m = c.borrow_mut(); *m +=1 } println!("c = {}", c.borrow()); // 获取不可变引用 |
Cell<T> | 概念:允许你修改内部地值,即使在不可变引用地情况下,但它只能用于被复制地类型(即实现 Copy 或 Clone地类型) 比喻:想象你有一块橡皮擦,你可以在任何时候使用它擦掉写下的字,即使书已经在别人手上。 用途:需要在不可变引用存在的情况下修改数据,但数据类型可以复制 例子: use std::cell::Cell; let d = Cell::new(5); // 创建一个 Cell d.set(6); // 修改数据 println!("d = {}", d.get()); // 获取数据 |
UnsafeCell<T> | 概念:是 Cell<T> 的基础,它允许你修改任何类型的值,但使用它时必须非常小心,因为它绕过了 Rust 的所有权和生命周期系统,可能会导致不安全的行为 比喻:想象你有一个魔法盒子,你可以随时修改里面的东西,但如果你不小心,可能会引发灾难 用途: 1.当你需要在不可变引用存在的情况下修改任何类型的数据,但需要非常小心以避免不安全的行为 |
12-19
1265

09-25
1万+
