rust中智能指針的實現(xiàn)
1、 什么是智能指針?Rust 三類指針對比
類型 | 安全性 | 借用檢查 | 是否自動釋放 | 功能特點 |
---|---|---|---|---|
&T, &mut T | ? 是 | ? 是 | ? 是 | 借用引用,不擁有數(shù)據(jù) |
*const T, *mut T | ? 否 | ? 否 | ? 否 | 原生裸指針,用于 FFI、底層控制 |
智能指針(如 Box) | ? 是 | ? 是/部分 | ? 是 | 擁有數(shù)據(jù),帶有自動釋放和額外功能 |
?? 智能指針本質(zhì)是一個擁有值的結(jié)構(gòu)體,實現(xiàn)了 Deref
和 Drop
,讓你可以像指針一樣訪問值,又能自動釋放資源。
2、原生指針 *const T:危險但有用
fn main() { let x = 5; let p: *const i32 = &x; // 獲取原生指針 unsafe { println!("值是:{}", *p); // 只有在 unsafe 代碼塊中才能解引用 } }
? 只讀,不會自動釋放。
? 無生命周期、越界檢查,容易懸垂。
?? 用于與 C 語言交互或?qū)崿F(xiàn)底層結(jié)構(gòu)。
手動釋放:Box::into_raw / from_raw
fn main() { let b = Box::new(42); let ptr = Box::into_raw(b); // 轉(zhuǎn)換為裸指針,不再自動釋放 unsafe { let b2 = Box::from_raw(ptr); // 重新接管所有權(quán) println!("恢復(fù)值:{}", b2); } // 自動釋放 }
?? 記?。?strong>誰 into_raw,誰就必須 from_raw,否則泄漏!
3、常見智能指針逐個講清
Box:在堆上分配值
fn main() { let b = Box::new(100); // 將整數(shù) 100 放到堆上 println!("b 的值是:{}", *b); // 解引用訪問 } // 離開作用域自動釋放(RAII)
適合:大對象、遞歸結(jié)構(gòu)、強(qiáng)制所有權(quán)轉(zhuǎn)移。
Rc:單線程引用計數(shù)共享
use std::rc::Rc; fn main() { let a = Rc::new("hello".to_string()); let b = Rc::clone(&a); // 引用計數(shù) +1 println!("a = {}, b = {}", a, b); // 多個變量共享同一塊內(nèi)存 }
適合:多個地方共享不可變數(shù)據(jù),如圖結(jié)構(gòu)、緩存。
?? 注意:不能用于多線程。
RefCell / Cell:內(nèi)部可變性
use std::cell::RefCell; fn main() { let x = RefCell::new(10); // 創(chuàng)建可變?nèi)萜? *x.borrow_mut() += 5; // 可變借用 println!("當(dāng)前值: {}", x.borrow()); }
- RefCell:運(yùn)行時借用檢查,支持引用。
- Cell:適合
Copy
類型的值,用 get/set 讀寫。
Cow:寫時復(fù)制,節(jié)省資源
use std::borrow::Cow; fn modify(input: Cow<str>) -> Cow<str> { if input.contains("x") { Cow::Owned(input.replace("x", "y")) // 真要改時才復(fù)制 } else { input } } fn main() { let s = Cow::Borrowed("hexo"); let result = modify(s); println!("結(jié)果:{}", result); }
適合:讀取多、寫入少的場景,如配置、模板處理。
Option 與智能指針
fn get_name() -> Option<&'static str> { Some("Tom") } fn main() { if let Some(name) = get_name() { println!("找到名字:{}", name); } }
Option 表示“可能有值”或“無值”,智能指針經(jīng)常作為 Option 的值使用,用于“延遲初始化”。
4、 并發(fā)智能指針
Arc:線程安全引用計數(shù)
use std::sync::Arc; fn main() { let a = Arc::new(42); let b = Arc::clone(&a); println!("a = {}, b = {}", a, b); }
?? 與 Rc 類似,但用原子操作實現(xiàn),適合多線程。
Mutex:互斥鎖保護(hù)數(shù)據(jù)
use std::sync::Mutex; fn main() { let m = Mutex::new(0); { let mut data = m.lock().unwrap(); *data += 1; } println!("當(dāng)前值: {:?}", m); }
?? 一次只能一個線程修改。
RwLock:讀多寫少,效率高
use std::sync::RwLock; fn main() { let lock = RwLock::new(10); { let r1 = lock.read().unwrap(); let r2 = lock.read().unwrap(); println!("讀者1: {}, 讀者2: {}", r1, r2); } { let mut w = lock.write().unwrap(); *w += 10; } println!("寫后值: {}", *lock.read().unwrap()); }
AtomicUsize:無鎖計數(shù)器
use std::sync::atomic::{AtomicUsize, Ordering}; fn main() { let counter = AtomicUsize::new(0); counter.fetch_add(1, Ordering::SeqCst); // 原子 +1 println!("計數(shù)器值: {}", counter.load(Ordering::SeqCst)); }
適合:高性能并發(fā)狀態(tài)計數(shù),如連接數(shù)、任務(wù)狀態(tài)。
5、高階用法組合:Arc<Mutex>
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 h in handles { h.join().unwrap(); } println!("最終結(jié)果: {}", *counter.lock().unwrap()); }
6、深入進(jìn)階:Weak / Pin / UnsafeCell
Weak:打破 Rc/Arc 的循環(huán)引用
use std::rc::{Rc, Weak}; use std::cell::RefCell; struct Node { next: RefCell<Option<Rc<Node>>>, prev: RefCell<Option<Weak<Node>>>, // 使用弱引用避免循環(huán) }
?? Rc::downgrade(&rc)
轉(zhuǎn)換為 Weak,不計入引用計數(shù)
?? .upgrade()
返回 Option<Rc>
Pin:防止對象被移動
use std::pin::Pin; fn main() { let data = String::from("hello"); let pinned = Pin::new(&data); println!("{}", pinned); }
?? 用于 Future、self-referential 結(jié)構(gòu)
?? Box::pin()
可固定對象
UnsafeCell:RefCell/Mutex 背后的魔法
use std::cell::UnsafeCell; struct MyType { data: UnsafeCell<i32>, } unsafe impl Sync for MyType {} fn main() { let x = MyType { data: UnsafeCell::new(0) }; unsafe { *x.data.get() = 42; println!("{}", *x.data.get()); } }
?? 允許穿透不可變引用進(jìn)行修改,底層實現(xiàn) RefCell、Mutex
場景速查表
類型 | 線程安全 | 可變性 | 常見用途 |
---|---|---|---|
Box | ? 否 | ? 是 | 所有權(quán)轉(zhuǎn)移,遞歸結(jié)構(gòu) |
Rc | ? 否 | ? 否 | 單線程共享只讀數(shù)據(jù) |
RefCell | ? 否 | ? 是 | 內(nèi)部可變性,運(yùn)行時借用檢查 |
Cell | ? 否 | ? 是 | Copy 類型小數(shù)據(jù)的替換 |
Cow | ? 是 | ? 是 | 寫時復(fù)制,節(jié)省資源 |
Arc | ? 是 | ? 否 | 多線程只讀共享 |
Mutex | ? 是 | ? 是 | 多線程可變共享 |
RwLock | ? 是 | ? 是 | 多讀單寫 |
AtomicUsize | ? 是 | ? 是 | 無鎖計數(shù)器,高性能狀態(tài)共享 |
Weak | ? 是 | ? 否 | 打破 Rc/Arc 循環(huán)引用 |
Pin | ? 是 | ? 否 | 防止移動,適用于異步/自引用結(jié)構(gòu) |
UnsafeCell | ?(需手動保證) | ? 是 | RefCell / Mutex 的底層支撐 |
總結(jié)建議
- 智能指針 = 擁有數(shù)據(jù) + 自動管理資源 + 像引用一樣使用
- Rc、RefCell 是組合神器,但要小心引用環(huán)
- Arc + Mutex 是并發(fā)安全的常見搭配
- 遇到底層問題,了解 Pin / UnsafeCell 能更深入掌握 Rust 內(nèi)存模型
到此這篇關(guān)于rust中智能指針的實現(xiàn)的文章就介紹到這了,更多相關(guān)rust 智能指針內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!