【笔记分享】`Cell<T>`与`RefCell<T>`的关联与差别

Cell<T>RefCell<T>有什么关联与差别

它们之间的相同点

  • 它们都是【共享+可修改】容器数据结构,而不是【智能指针】,因为其没有实现Deref traitDerefMut trait

  • 它们都只能被使用在【单线程】环境下,因为其皆未实现Sync trait

  • 它们都允许内部值T以受控方式被“修改”,虽然其已经同时被多个【只读-引用】所指向。

    • 前者只能算是【替换】(内部值T)--- 【可修改】是就Cell<T>自身而言的,Cell<T>内部值变了(别管怎么变的),反正Cell<T>的值就是不一样了。感觉它偷换概念,欺负我读书少

    • 后者才是【修改】--- 【可修改】是就内部值T所在内存地址上的内容而言的,内部值T的内存位置没有变,而是那个地址上的东西变了。这明显更高级

    • 对于Cell<T>RefCell<T>,“修改”的含义不一样:

    • 它们提供的这个能力被统称为【内部可修改】。这是相较于普通rust类型的【继承可修改】而言。

  • 它们仅只”打破“了传统的“【只读引用】不能与【可修改引用】共存”的限制。但是,在【同一时刻+同一作用域】内,【可修改引用】还至多只能有一个。否则,要么,编译错误;要么,运行时崩溃。

它们之间的不同点

82311569dd45a7d4dcafd191d0e2aeb6.png

上图的文字描述如下:

本质不同

  • Cell<T>“包含”的是【所有权】变量本身

  • RefCell<T>“包含”的是变量的【引用】。即便RefCell::new(...)构造函数的实参是【所有权】变量,这也不影响其内部重点使用该变量的【内存地址】。

衍生不同

  • 检查时间点

    • 运行时,确保:对内部值【临时的+排他的+可修改的】访问

    • Cell<T>编译时,代码静态扫描,借入检查

    • RefCell<T>运行时,动态跟踪,借入检查

  • 违背【借入规则】的后果

    • Cell<T>违背【借入规则】的代码会导致【编译失败】

    • RefCell<T>违背【借入规则】的代码会导致【运行时-程序崩溃panic

  • 计算成本

    • Cell<T>编译时成本

    • RefCell<T>运行时成本

  • 读取【容器数据结构】内部值

    • 要么,将【内部值】复制出来。比如,

    • 要么,将【内部值】置换出来。比如,

    • 要么,“杀鸡取卵”将【容器数据结构】“消费consume”掉,再将【内部值】真取出来。比如,

    • Cell<T: Copy>::get()

    • Cell<T: Default>::take()以类型默认值置换出来

    • Cell<T>::replace()以指定的值置换出来

    • Cell<T>::into_inner()

    • Cell<T>

    • RefCell<T>就三步:

  1. 通过【运行时-借入检查器】的审查

  2. RefCell<T>::borrow()取出变量的内存地址

  3. *RefCell<T>::borrow()以【去引用-操作符】取出该地址位置上被保存的值。

修改【容器数据结构】内部值:

  • Cell<T>::replace()以【新】值置换出【旧】值

  • Cell<T>::set()放入【新】值而直接丢弃【旧】值

  • Cell<T>

  • RefCell<T>

  1. 通过【运行时-借入检查器】的审查

  2. RefCell<T>::borrow_mut()取出变量的内存地址

  3. *RefCell<T>::borrow_mut()以【去引用-操作符】修改该地址位置上被保存的值。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值