Rust标准库学习-Cell

基本安全性约束

rust通过两种方式保证对象T的内存安全性:

1. 允许存在多个不可变的引用 &T 进行访问

2. 只允许一个可变的引用 &mut T 进行访问

并且1和2不能同时使用,要么使用多个不可变引用,要么只使用一个可变引用。

**所有者本身既可以是可变引用,也可以是不可变引用。

举个例子

    let mut vec = vec![1, 2, 3];
    let im_ref = &vec;
    for i in 0..10 {
        vec.push(i);
        println!("now vec {:?}", im_ref);
    }

编译器会报错,因为不可变引用im_ref在使用过程中进行了可变引用的访问(vec自身);这个在其他语言来看非常不可理喻,在rust中是安全性的基石。

虽然使用上障碍非常大,但是给予了引用强而可靠的安全性,即&T拿到的数据始终不变。

cell

下面说到标准库的cell模块,全名是std::cell

有时,我们需要多个可变的引用,cell就是为此而设计的一种对象容器。

cell模块提供了三种结构,Cell<T>、RefCell<T>和OnceCell<T>,注意这些容器都拥有了T的所有权,这三个容器的实现方式和使用场景有所区别,但效果都是使用对Cell的多个不可变引用&Cell,提供方法返回可修改的内部对象。即允许多个T可变的&Cell同时使用。

注意cell结构都不支持同步Sync特征,不支持多线程访问。并且显然,&Cell<T>也不再保证T的不可变性。

Cell<T>

通过所有权转移实现的Cell,该结构的方法一般会使用所有权移交的方式去提供可修改的T,当T实现了Copy时,get方法会进行数据拷贝(总之就是move的语义)

用于一些简单类型如数字。

RefCell<T>

以引用的形式,临时获取可变引用去提供可修改的T,同时间多个RefCell获取可变引用,在单线程中并不会出现“同时”出现多个实际的&mut T,如果同时出现,会直接触发运行时panic,当然这也违背了静态检查引用安全性的基本规则,所以引入RefCell实现可变性也是一种最后的手段。

OnceCell<T>

OnceCell是结合了Cell和RefCell的两种特点,允许所有权转移,也允许获取可变或不可变引用。

改写之前提到的例子如下:

    let vec = vec![1, 2, 3];
    let cell_vec = RefCell::new(vec);
    let cell_vec_ref = &cell_vec;
    for i in 0..10 {
        cell_vec.borrow_mut().push(i);
        println!("now vec {:?}", cell_vec_ref.borrow());
    }

程序能够正常执行,注意RefCell的borrow_mut返回了可修改的内部可变引用,跳过了静态检查。(注意这里我没有将borrow_mut赋值到一个临时变量中,如果赋值了,一定要使用语句块将他及时释放,否则下次使用borrow或borrow_mut必定会导致运行时panic

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值