田田妈 發表於 2025-6-27 09:44:02

rust中智能指针的实现

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>1、 什么是智能指针?Rust 三类指针对比</li><li>2、原生指针&nbsp;*const T:危险但有用</li><ul class="second_class_ul"><li>手动释放:Box::into_raw / from_raw</li></ul><li>3、常见智能指针逐个讲清</li><ul class="second_class_ul"><li>Box:在堆上分配值</li><li>Rc:单线程引用计数共享</li><li>RefCell / Cell:内部可变性</li><li>Cow:写时复制,节省资源</li><li>Option 与智能指针</li></ul><li>4、 并发智能指针</li><ul class="second_class_ul"><li>Arc:线程安全引用计数</li><li>Mutex:互斥锁保护数据</li><li>RwLock:读多写少,效率高</li><li>AtomicUsize:无锁计数器</li></ul><li>5、高阶用法组合:Arc&lt;Mutex&gt;</li><ul class="second_class_ul"></ul><li>6、深入进阶:Weak / Pin / UnsafeCell</li><ul class="second_class_ul"><li>Weak:打破 Rc/Arc 的循环引用</li><li>Pin:防止对象被移动</li><li>UnsafeCell:RefCell/Mutex 背后的魔法</li></ul><li>场景速查表</li><ul class="second_class_ul"></ul><li>总结建议</li><ul class="second_class_ul"></ul></ul></div><p class="maodian"></p><h2>1、 什么是智能指针?Rust 三类指针对比</h2>
<table><tbody><tr><th>类型</th><th>安全性</th><th>借用检查</th><th>是否自动释放</th><th>功能特点</th></tr><tr><td>&amp;T,&nbsp;&amp;mut T</td><td>✅ 是</td><td>✅ 是</td><td>✅ 是</td><td>借用引用,不拥有数据</td></tr><tr><td>*const T,&nbsp;*mut T</td><td>❌ 否</td><td>❌ 否</td><td>❌ 否</td><td>原生裸指针,用于 FFI、底层控制</td></tr><tr><td>智能指针(如 Box)</td><td>✅ 是</td><td>✅ 是/部分</td><td>✅ 是</td><td>拥有数据,带有自动释放和额外功能</td></tr></tbody></table>
<p>📌 智能指针本质是一个<strong>拥有值的结构体</strong>,实现了&nbsp;<code>Deref</code>&nbsp;和&nbsp;<code>Drop</code>,让你可以像指针一样访问值,又能自动释放资源。</p>
<p class="maodian"></p><h2>2、原生指针&nbsp;*const T:危险但有用</h2>
<div class="jb51code"><pre class="brush:plain;">fn main() {
    let x = 5;
    let p: *const i32 = &amp;x; // 获取原生指针

    unsafe {
      println!("值是:{}", *p); // 只有在 unsafe 代码块中才能解引用
    }
}
</pre></div>
<p>✅ 只读,不会自动释放。<br />❌ 无生命周期、越界检查,容易悬垂。<br />💡 用于与 C 语言交互或实现底层结构。</p>
<p class="maodian"></p><h3>手动释放:Box::into_raw / from_raw</h3>
<div class="jb51code"><pre class="brush:xhtml;">fn main() {
    let b = Box::new(42);
    let ptr = Box::into_raw(b);         // 转换为裸指针,不再自动释放

    unsafe {
      let b2 = Box::from_raw(ptr);    // 重新接管所有权
      println!("恢复值:{}", b2);
    } // 自动释放
}
</pre></div>
<p>📌 记住:<strong>谁 into_raw,谁就必须 from_raw,否则泄漏!</strong></p>
<p class="maodian"></p><h2>3、常见智能指针逐个讲清</h2>
<p class="maodian"></p><h3>Box:在堆上分配值</h3>
<div class="jb51code"><pre class="brush:plain;">fn main() {
    let b = Box::new(100);            // 将整数 100 放到堆上
    println!("b 的值是:{}", *b);       // 解引用访问
} // 离开作用域自动释放(RAII)
</pre></div>
<p>适合:大对象、递归结构、强制所有权转移。</p>
<p class="maodian"></p><h3>Rc:单线程引用计数共享</h3>
<div class="jb51code"><pre class="brush:plain;">use std::rc::Rc;

fn main() {
    let a = Rc::new("hello".to_string());
    let b = Rc::clone(&amp;a);            // 引用计数 +1
    println!("a = {}, b = {}", a, b);   // 多个变量共享同一块内存
}
</pre></div>
<p>适合:<strong>多个地方共享不可变数据</strong>,如图结构、缓存。<br />📛 注意:不能用于多线程。</p>
<p class="maodian"></p><h3>RefCell / Cell:内部可变性</h3>
<div class="jb51code"><pre class="brush:plain;">use std::cell::RefCell;

fn main() {
    let x = RefCell::new(10);         // 创建可变容器
    *x.borrow_mut() += 5;               // 可变借用
    println!("当前值: {}", x.borrow());
}
</pre></div>
<ul><li>RefCell:运行时借用检查,支持引用。</li><li>Cell:适合&nbsp;<code>Copy</code>&nbsp;类型的值,用 get/set 读写。</li></ul>
<p class="maodian"></p><h3>Cow:写时复制,节省资源</h3>
<div class="jb51code"><pre class="brush:plain;">use std::borrow::Cow;

fn modify(input: Cow&lt;str&gt;) -&gt; Cow&lt;str&gt; {
    if input.contains("x") {
      Cow::Owned(input.replace("x", "y")) // 真要改时才复制
    } else {
      input
    }
}

fn main() {
    let s = Cow::Borrowed("hexo");
    let result = modify(s);
    println!("结果:{}", result);
}
</pre></div>
<p>适合:读取多、写入少的场景,如配置、模板处理。</p>
<p class="maodian"></p><h3>Option 与智能指针</h3>
<div class="jb51code"><pre class="brush:plain;">fn get_name() -&gt; Option&lt;&amp;'static str&gt; {
    Some("Tom")
}

fn main() {
    if let Some(name) = get_name() {
      println!("找到名字:{}", name);
    }
}
</pre></div>
<p>Option 表示&ldquo;可能有值&rdquo;或&ldquo;无值&rdquo;,智能指针经常作为 Option 的值使用,用于&ldquo;延迟初始化&rdquo;。</p>
<p class="maodian"></p><h2>4、 并发智能指针</h2>
<p class="maodian"></p><h3>Arc:线程安全引用计数</h3>
<div class="jb51code"><pre class="brush:plain;">use std::sync::Arc;

fn main() {
    let a = Arc::new(42);
    let b = Arc::clone(&amp;a);
    println!("a = {}, b = {}", a, b);
}
</pre></div>
<p>🧠 与 Rc 类似,但用原子操作实现,适合多线程。</p>
<p class="maodian"></p><h3>Mutex:互斥锁保护数据</h3>
<div class="jb51code"><pre class="brush:plain;">use std::sync::Mutex;

fn main() {
    let m = Mutex::new(0);
    {
      let mut data = m.lock().unwrap();
      *data += 1;
    }
    println!("当前值: {:?}", m);
}
</pre></div>
<p>📌 一次只能一个线程修改。</p>
<p class="maodian"></p><h3>RwLock:读多写少,效率高</h3>
<div class="jb51code"><pre class="brush:plain;">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());
}
</pre></div>
<p class="maodian"></p><h3>AtomicUsize:无锁计数器</h3>
<div class="jb51code"><pre class="brush:plain;">use std::sync::atomic::{AtomicUsize, Ordering};

fn main() {
    let counter = AtomicUsize::new(0);
    counter.fetch_add(1, Ordering::SeqCst); // 原子 +1
    println!("计数器值: {}", counter.load(Ordering::SeqCst));
}
</pre></div>
<p>适合:高性能并发状态计数,如连接数、任务状态。</p>
<p class="maodian"></p><h2>5、高阶用法组合:Arc&lt;Mutex&gt;</h2>
<div class="jb51code"><pre class="brush:plain;">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(&amp;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!("最终结果: {}", *counter.lock().unwrap());
}
</pre></div>
<p class="maodian"></p><h2>6、深入进阶:Weak / Pin / UnsafeCell</h2>
<p class="maodian"></p><h3>Weak:打破 Rc/Arc 的循环引用</h3>
<div class="jb51code"><pre class="brush:plain;">use std::rc::{Rc, Weak};
use std::cell::RefCell;

struct Node {
    next: RefCell&lt;Option&lt;Rc&lt;Node&gt;&gt;&gt;,
    prev: RefCell&lt;Option&lt;Weak&lt;Node&gt;&gt;&gt;, // 使用弱引用避免循环
}
</pre></div>
<p>📌&nbsp;<code>Rc::downgrade(&amp;rc)</code>&nbsp;转换为 Weak,不计入引用计数<br />📌&nbsp;<code>.upgrade()</code>&nbsp;返回 Option&lt;Rc&gt;</p>
<p class="maodian"></p><h3>Pin:防止对象被移动</h3>
<div class="jb51code"><pre class="brush:plain;">use std::pin::Pin;

fn main() {
    let data = String::from("hello");
    let pinned = Pin::new(&amp;data);
    println!("{}", pinned);
}
</pre></div>
<p>📌 用于 Future、self-referential 结构<br />📌&nbsp;<code>Box::pin()</code>&nbsp;可固定对象</p>
<p class="maodian"></p><h3>UnsafeCell:RefCell/Mutex 背后的魔法</h3>
<div class="jb51code"><pre class="brush:plain;">use std::cell::UnsafeCell;

struct MyType {
    data: UnsafeCell&lt;i32&gt;,
}

unsafe impl Sync for MyType {}

fn main() {
    let x = MyType { data: UnsafeCell::new(0) };

    unsafe {
      *x.data.get() = 42;
      println!("{}", *x.data.get());
    }
}
</pre></div>
<p>📌 允许<strong>穿透不可变引用</strong>进行修改,底层实现 RefCell、Mutex</p>
<p class="maodian"></p><h2>场景速查表</h2>
<table><tbody><tr><th>类型</th><th>线程安全</th><th>可变性</th><th>常见用途</th></tr><tr><td>Box</td><td>❌ 否</td><td>✅ 是</td><td>所有权转移,递归结构</td></tr><tr><td>Rc</td><td>❌ 否</td><td>❌ 否</td><td>单线程共享只读数据</td></tr><tr><td>RefCell</td><td>❌ 否</td><td>✅ 是</td><td>内部可变性,运行时借用检查</td></tr><tr><td>Cell</td><td>❌ 否</td><td>✅ 是</td><td>Copy 类型小数据的替换</td></tr><tr><td>Cow</td><td>✅ 是</td><td>✅ 是</td><td>写时复制,节省资源</td></tr><tr><td>Arc</td><td>✅ 是</td><td>❌ 否</td><td>多线程只读共享</td></tr><tr><td>Mutex</td><td>✅ 是</td><td>✅ 是</td><td>多线程可变共享</td></tr><tr><td>RwLock</td><td>✅ 是</td><td>✅ 是</td><td>多读单写</td></tr><tr><td>AtomicUsize</td><td>✅ 是</td><td>✅ 是</td><td>无锁计数器,高性能状态共享</td></tr><tr><td>Weak</td><td>✅ 是</td><td>❌ 否</td><td>打破 Rc/Arc 循环引用</td></tr><tr><td>Pin</td><td>✅ 是</td><td>❌ 否</td><td>防止移动,适用于异步/自引用结构</td></tr><tr><td>UnsafeCell</td><td>❌(需手动保证)</td><td>✅ 是</td><td>RefCell / Mutex 的底层支撑</td></tr></tbody></table>
<p class="maodian"></p><h2>总结建议</h2>
<ul><li>智能指针 = 拥有数据 + 自动管理资源 + 像引用一样使用</li><li>Rc、RefCell 是组合神器,但要小心引用环</li><li>Arc + Mutex 是并发安全的常见搭配</li><li>遇到底层问题,了解 Pin / UnsafeCell 能更深入掌握 Rust 内存模型</li></ul>
<p>到此这篇关于rust中智能指针的实现的文章就介绍到这了,更多相关rust 智能指针内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!&nbsp;</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>解读Rust的Rc&lt;T&gt;:实现多所有权的智能指针方式</li><li>Rust之智能指针的用法</li><li>Rust&nbsp;智能指针实现方法</li><li>rust智能指针的具体使用</li><li>详解rust 自动化测试、迭代器与闭包、智能指针、无畏并发</li><li>Rust&nbsp;智能指针的使用详解</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: rust中智能指针的实现