做淘宝要网站,佛山市网站建设企业,网站建设管理人员工作职责,做微商想做个网站Rust中的智能指针 什么是智能指针#xff1f;什么是Rust中的智能指针#xff1f;Rust中的智能指针BoxBox的使用场景 Rust中的智能指针Rc与Arcrust中的RefCellrefcell的缺点#xff1a;rust中的weak先来看看C中的weak_ptr定义代码示例#xff1a; Deref和Drop 总结 什么是智… Rust中的智能指针 什么是智能指针什么是Rust中的智能指针Rust中的智能指针BoxBox的使用场景 Rust中的智能指针Rc与Arcrust中的RefCellrefcell的缺点rust中的weak先来看看C中的weak_ptr定义代码示例 Deref和Drop 总结 什么是智能指针
传统的指针如C中的裸指针需要开发者自己申请和释放如果开发者在使用过程中疏漏了回收将会造成内存泄漏在部署 实施时也会有oom的风险智能指针即是为了解决这类问题而出现的老生常谈的shared_ptrunique_ptrweak_ptr等都是通过设计使得代码自动管理回收堆上的内存提高代码的健壮性和方便性。 什么是Rust中的智能指针
Rust由于其严格的安全性和所有权机制除unsafe写法外所有的堆内存都是通过语言特性管理的。其目的和其他语言一致都是为了健壮性和方便使用与C的智能指针使用的机制并无二致都是使用了RAII即资源获取即初始化常见的rust智能指针有BoxRcArcWeak等。(个人理解因为rust中的智能指针常与引用符号结合使用与其叫做智能指针不如叫智能引用。)
Rust中的智能指针Box
首先看一下C中的unique_ptr: 1.unique_ptr所指向(引用)的资源只能被unique_ptr所独占,不能被Copy,只能被转移。 2.自动析构不计数(结合一中的定义独占型指针也没有任何计数的必要) 以上是unique_ptr的特点这也是Rust中Box的主要特点 只能转移所有权不能Copy同时只能有一个有效的Box。
Box的使用场景
由于Box的独占特点其使用一般可以用在
避免深拷贝一些多字节的数据此文中提到的特征对象作为返回值使用,个人理解这是Box的最有用且最常用之处。作为容器中得item如:
vec![Boxdyn Noise] //比较适合在实践一些设计模式时使用代码示例
fn returns_noise(isdog: bool) - Boxdyn Noise {if isdog {Box::new(Dog {voice: String::from(wangwang,),})} else {Box::new(Cat {voice: String::from(miaomiao,),})}
} Rust中的智能指针Rc与Arc Rc: 全称 Reference Count即引用计数。 Arc: 全称Atomic Reference Count即原子性引用计数。 由定义可知Arc对比与Rc的一大优点就是原子性既线程安全。而实现了线程安全势必要损失了一些性能所以Rc比Arc性能要更好些这两个智能指针都是只读的 。 Rc与C中的Shared_ptr机制类似都是通过引用计数和RAII最终实现对于堆内存的自动控制两者都是线程不安全的最大的区别便是Rc只读。 代码示例
{ let rc1 Rc::new(String::from(hello world));let rc2 Rc::clone(rc1);let rc3 Rc::clone(rc1);
}{ let mystr String::from(hello world);let bx2 Box::new(mystr);let bx3 Box::new(mystr);//got error
}以上是Rc与Box间的对比由于所有权的转移bx3在二次借用时便会出错而rc拥有计数规则上述代码将通过编译。 这里细心的同学会留意到clone这里只是浅拷贝。 原则上栈上数据基本都可以直接复制而堆上内存申请性能相对较慢堆上内存非必要情况下不做深拷贝同理如果你作为一个语言开发者非必要情况下也不会默认将堆上内存直接深拷贝。 Arc是Rc的线程安全版本用法函数基本一致不做代码示例有需要可用自行查阅。
rust中的RefCell
在之前我们提到过Rc与C中的shared_ptr很接近但是是只读的如何做到内部可变 — 结合RefCell。 内部可变在不改变外部套壳的情况下可更改内部数值。 let s Rc::new(RefCell::new(hello .to_string()));let s1 s.clone();let s2 s.clone();s2.borrom_mut().push_str(world);println!({:?},s);println!({:?},s1);println!({:?},s2);均打印出 hello world refcell的缺点
代码使用了refcell后rust被遵循的借用三大规则被移动到运行时强制panic(也算比较安全至少比unsafe从字面上的来看更舒服些)
rust中的weak
先来看看C中的weak_ptr定义 std::weak_ptr is a smart pointer that holds a non-owning (“weak”) reference to an object that is managed by std::shared_ptr. It must be converted to std::shared_ptr in order to access the referenced object. std::weak_ptr models temporary ownership: when an object needs to be accessed only if it exists, and it may be deleted at any time by someone else, std::weak_ptr is used to track the object, and it is converted to std::shared_ptr to acquire temporary ownership. If the original std::shared_ptr is destroyed at this time, the object’s lifetime is extended until the temporary std::shared_ptr is destroyed as well. Another use for std::weak_ptr is to break reference cycles formed by objects managed by std::shared_ptr. If such cycle is orphaned (i.e., there are no outside shared pointers into the cycle), the shared_ptr reference counts cannot reach zero and the memory is leaked. To prevent this, one of the pointers in the cycle can be made weak. 总之weak_ptr很弱只记录状态信息不保证一定存在同时(主要)为了解决shared_ptr造成的循环引用通常也不会单独出现必须要转换成shared_ptr. 对比rust中的weak也是几乎一样的设计理由和使用条件不保证引用一定存在所以它返回Option Rc T ,代码写法即upgrade升级到Rc或将Rc降级到weak。
代码示例
use std::rc::{Rc, Weak};
use std::cell::RefCell;
#[derive(Debug)]
struct Node {value: i32,parent: RefCellWeakNode,children: RefCellVecRcNode,
}fn main() {let _leaf Rc::new(Node {value: 3,parent: RefCell::new(Weak::new()),children: RefCell::new(vec![]),});
}Deref和Drop
Deref: 将引用中的实际值解出并使用是Rust中最常见的隐式转换如将String类型传入 str入参时等等Drop: 释放资源类似于析构函数同样的有默认实现也有主动重写。Deref 是特征一般开发者仅会为自定义的智能指针实现解引用特征。解引用可递推所以在隐式转换时常常有多层的解引用。
总结
本章结合题目非常适合链表练习。
如有勘误敬请指出。