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)、強制所有權(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:運行時借用檢查,支持引用。
- 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:互斥鎖保護數(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、深入進階: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());
}
}
?? 允許穿透不可變引用進行修改,底層實現(xiàn) RefCell、Mutex
場景速查表
| 類型 | 線程安全 | 可變性 | 常見用途 |
|---|---|---|---|
| Box | ? 否 | ? 是 | 所有權(quán)轉(zhuǎn)移,遞歸結(jié)構(gòu) |
| Rc | ? 否 | ? 否 | 單線程共享只讀數(shù)據(jù) |
| RefCell | ? 否 | ? 是 | 內(nèi)部可變性,運行時借用檢查 |
| 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)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Rust中用enum實現(xiàn)多參數(shù)Hook機制完整代碼
在 Rust 中,如果想為enum實現(xiàn)一個帶多參數(shù)的 Hook 機制,可以結(jié)合模式匹配和枚舉來處理,這種方式可以擴展到支持不同類型的輸入?yún)?shù)和邏輯處理,下面通過示例代碼介紹Rust中用enum實現(xiàn)多參數(shù)Hook機制,感興趣的朋友一起看看吧2024-12-12
rust中間件actix_web在項目中的使用實戰(zhàn)
這篇文章主要介紹了rust中間件在項目中的使用實戰(zhàn),包括自定義中間件,日志中間件,Default?headers,用戶會話,錯誤處理的用法實例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2024-01-01

