RefCell 数据类型
内部可变性(interior mutability)是RUST的设计模式之一,它允许你在只持有不可变引用的前提下对数据进行修改。为了能改变数据,内部可变性模式在它的数据结构中使用了unsafe(不安全)代码来绕过RUST正常的可变性和借用规则。
假如我们能够保证自己的代码在运行时符合借用规则,那么即使编译器无法在编译阶段保证符合借用规则,也能使用那些采用了内部可变性模式的类型。
对于一般引用和Box<T>的代码,RUST会在编译阶段强制代码遵守借用规则。而对于RefCell<T>的代码,RUST则只会在运行时检查这些规则,并在违反借用规则的情况下触发panic来终止程序。
与Rc<T>相似,RefCell<T>只能被用于单线程场景中。强行将它用于多线程环境中会产生编译时错误。下面是选择使用Box<T>、Rc<T>和RefCell<T>的依据:
Rc<T>允许一份数据有多个所有者,而Box<T>和RefCell<T>都只有一个所有者Box<T>允许在编译时检查可变或不可变借用,Rc<T>仅允许编译时检查不可变借用,RefCell<T>允许运行时检查可变或不可变借用。- 由于
RefCell<T>允许我们在运行时检查可变借用,所以即使RefCell<T>本身是不可变的,我们仍然能够更改其中存储的值。
pub trait Messager {fn send(&self, msg: &str);
}pub struct LimitTracker<'a, T: 'a + Messager> {messager: &'a T,value: usize,
}impl<'a, T> LimitTracker<'a, T>
whereT: Messager,
{pub fn new(messager: &T, value: usize) -> LimitTracker<T> {LimitTracker {messager: messager,value: value,}}pub fn set_value(&mut self, value: usize) {self.value = value;self.messager.send("msg");}
}
这段代码的重点是Messager trait,它唯一的send方法可以接受self的不可变引用及一条文本消息作为参数。
示例的结构体同时使用生命周期标注和泛型约束,结构体实现关联函数new和方法set_value。紧跟impl后的尖括号声明指明结构体自身的约束。
下面对set_value做单元测试,mock一个实现了Message trait的结构体MockMessage进行验证,调用send方法会向结构体字段中写入值。
#[cfg(test)]
mod test {use super::*;struct MockMessage {sent_message: Vec<String>,}impl MockMessage {fn new() -> MockMessage {MockMessage {sent_message: vec![],}}}impl Messager for MockMessage {fn send(&self, msg: &str) {self.sent_message.push(String::from(msg));}}#[test]fn send_warning_message() {let mock_messager = MockMessage::new();let mut limit_tracker = LimitTracker::new(&mock_messager, 2);limit_tracker.set_value(10);}
}
编译器报错,send方法接收的self属于不可变引用,我们无法修改MockMessage中的内容。如果将send方法self修改为&mut self又不符合Messager trait约束。
在保持外部值不可变的前提下,使用RefCell<T>来修改内部存储的值。sent_message字段类型调整成RefCell<Vec<String>>,最后调整成下面这个样子:
#[cfg(test)]
mod test {use super::*;use std::cell::RefCell;struct MockMessage {sent_message: RefCell<Vec<String>>,}impl MockMessage {fn new() -> MockMessage {MockMessage {sent_message: RefCell::new(vec![]),}}}impl Messager for MockMessage {fn send(&self, msg: &str) {self.sent_message.borrow_mut().push(String::from(msg));}}#[test]fn send_warning_message() {let mock_messager = MockMessage::new();let mut limit_tracker = LimitTracker::new(&mock_messager, 2);limit_tracker.set_value(10);}
}
我们调用RefCell<Vec<String>>类型的borrow_mut方法来获取内部值的可变引用,接着,我们便可以在动态数据的可变引用上调用push方法来存入数据。
我们会在创建不可变引用和可变引用时分别使用语法&和&mut。RefCell<T>实现了borrow和borrow_mut方法分别返回Ref<T>与RefMut<T>这两种智能指针。由于这两种指针都实现了Deref,所以我们可以把它们当做一般的引用来对待。
RefCell<T>会记录当前存在多少个活跃的Ref<T>和RefMut<T>智能指针,在任何一个给定的时间里,它只允许你拥有多个不可变借用和一个可变借用。当我们违背借用规则时,相比于一般引用导致的编译错误,RefCell<T>会在运行时触发panic。
相关文章:
RefCell 数据类型
内部可变性(interior mutability)是RUST的设计模式之一,它允许你在只持有不可变引用的前提下对数据进行修改。为了能改变数据,内部可变性模式在它的数据结构中使用了unsafe(不安全)代码来绕过RUST正常的可变…...
[oeasy]python0002_终端_CLI_GUI_编程环境_游戏_真实_元宇宙
回忆 上次 了解了 python 语言的特点 历史悠久功能强大深受好评已成趋势 3大主流操作系统 macwindowslinux 我们 选择 linux 作为基础系统 为什么选择 黑乎乎的命令行界面呢?🤔 GUI vs CLI 个人电脑 用图标和菜单组成 图形界面(GUI) Graphic User I…...
微服务1 springcloud学习笔记P1-P40
b微服务技术栈_哔哩哔哩_bilibili 文档资料: 链接:https://pan.baidu.com/s/1P_Ag1BYiPaF52EI19A0YRw?pwdd03r 提取码:d03r 一 了解微服务技术 二 Eureka (1) Eureka配置 (2) 注册user-service (3) 总结 Ribbon 负载均衡 (1) 流程 三 nacos配置管理…...
【页面】表格展示
展示 Dom <template><div class"srch-result-container"><!--左侧--><div class"left"><div v-for"(item,index) in muneList" :key"index" :class"(muneIndexitem.mm)?active:"click"pa…...
天池SQL训练营(六)-综合练习题-10道经典题目
如果你还没有学习过SQL训练营的以下知识,请查阅主页博文学习: Task 1 SQL基础:初识数据库与SQL-安装与基本介绍等 Task 2 SQL基础:查询与排序-select、运算符、聚合分组查询等 Task 3 SQL进阶:复杂查询方法-视图、子查…...
某校园报名sign解密
某校园报名sign解密 定位 看了下确实是md5标准算法,接下来就看下加密的明文了 最后分开看了下, sign md5(用户名 活动id 10位时间戳 keys)...
2024年安防视频监控行业将面临4大机遇和挑战
当前安防监控市场处于快速发展的阶段,市场不仅有传统的视频监控、门禁系统等单一功能的设备,还涌现出了一系列集成多种安防功能的综合系统。随着人工智能技术的发展,安防监控设备不仅可以对场所进行实时监控,还可以通过图像识别、…...
搞懂HashTable, HashMap, ConcurrentHashMap 的区别,看着一篇就足够了!!!
🛩️🛩️🛩️ 今天给大家分享的是 HashTable, HashMap, ConcurrentHashMap之间的区别,也是自己学习过程中的总结。 清风的CSDN博客 🛩️🛩️🛩️希望我的文章能对你有所帮助,有不足的…...
PostgreSQL 技术内幕(十二) CloudberryDB 并行化查询之路
随着数据驱动的应用日益增多,数据查询和分析的量级和时效性要求也在不断提升,对数据库的查询性能提出了更高的要求。为了满足这一需求,数据库引擎不断经历创新,其中并行执行引擎是性能提升的重要手段之一,逐渐成为数据…...
Vue学习计划-Vue2--Vue核心(七)生命周期
抛出问题:一进入页面就开启一个定时器,每隔1秒count就加1,如何实现 示例: <body> <div id"app">{{ n }}<button click"add">执行</button> </div><script>let vm new …...
前端知识笔记(三十四)———HBuilder的下载与使用(详细步骤)
一、HBuilder IDE的下载 HBuilder下载官网地址: 在地址栏中直接输入https://www.dcloud.io 或者直接点击下面的链接 DCloud - HBuilder、HBuilderX、uni-app、uniapp、5、5plus、mui、wap2app、流应用、HTML5、小程序开发、跨平台App、多端框架 进入官网&#x…...
stl容器
大部分容器的size的复杂度如下: std::vector: 时间复杂度为(1). std::deque: 时间复杂度为 O(1). 双端队列 std::list: 时间复杂度为 O(1)(C11 及以后的版本)。 std::forward_list: 时间复…...
android https 证书过期
有的时候 我们android https 证书过期 ,或者使用明文等方式去访问服务器 可能会碰到类似的 问题 : javax.net.ssl.SSLHandshakeException: Chain validation failed java.security.cert.CertPathValidatorException: Response is unreliable: its validi…...
lv11 嵌入式开发 中断控制器14
目录 1 中断控制器 编辑 2 Exynos4412下的中断控制器 2.1 概述 2.2 特征 编辑 2.3 中断状态 2.4 中断类型 2.5 中断控制器GIC中断表 3 中断控制器寄存器详解 3.1 ICDDCR(Interrupt Controller Distributor Control Register) 3.2 ICDISER…...
IDEA 出现问题:Idea-操作多次commit,如何合并为一个并push解决方案
❤️作者主页:小虚竹 ❤️作者简介:大家好,我是小虚竹。2022年度博客之星评选TOP 10🏆,Java领域优质创作者🏆,CSDN博客专家🏆,华为云享专家🏆,掘金年度人气作…...
贝蒂的捣蛋小游戏~(C语言)
引言: 前面贝蒂已经给大家介绍了选择,循环结构~,今天贝蒂就基于这两种结构,为大家讲解一种捣蛋小游戏的设计思路和方法哦。 1.游戏要求 游戏要求: 1. 电脑⾃动⽣成1~100的随机数 2. 玩家猜数字,猜数字的过…...
c# 判断是否连接公网
有一个需求,软件需要在连接公网的状态下才能使用,否则弹出提示 我们判断一下网络不通情况 1.系统未开启网络:例如关掉了WIFI,拔掉网线 2.网络已连接无internet:连接了路由器,但路由器未连接外网 对于以上…...
unity 2d 入门 飞翔小鸟 场景延续(八)
1、新建c#脚本如下 代码,在前方生成生成自身图片并3s后销毁自身,在碰撞物体后小鸟死亡后不删除自身 using System.Collections; using System.Collections.Generic; using UnityEngine;public class CopyScene : MonoBehaviour { //要复制的对象public…...
scrapy介绍,并创建第一个项目
一、scrapy简介 scrapy的概念 Scrapy是一个Python编写的开源网络爬虫框架。它是一个被设计用于爬取网络数据、提取结构性数据的框架。 Scrapy 使用了Twisted异步网络框架,可以加快我们的下载速度。 Scrapy文档地址:http://scrapy-chs.readthedocs.io/z…...
Rust语言项目实战(九 - 完结) - 胜利与失败
回顾 在前面的章节中,我们已经实现了这个游戏中大部分的模块和功能,我们可以指挥我们的战机左右移动,并发射子弹;我们还创造了一堆的侵略者,从屏幕上方缓缓降落,试图到达屏幕的底部。 本章中,我们将对游戏的输赢作出最后的裁决,到底是我们的保卫者英勇无敌,还是侵略…...
初创团队如何利用Token Plan套餐有效控制AI开发成本
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 初创团队如何利用Token Plan套餐有效控制AI开发成本 对于资源有限的初创团队和独立开发者而言,在原型开发和产品验证阶…...
【作品集】OpenClaw-AgentOps企业级多智能体贵金属交易分析平台
项目名称:OpenClaw-AgentOps 企业级多智能体贵金属交易分析平台 展示方式:保留原有项目架构图,同时加入系统真实页面切片,用“设计图 实物图”的方式完整展示项目。1. 项目一句话介绍OpenClaw-AgentOps 是一个面向贵金属交易研究…...
KLOGG:专业开发者的海量日志分析利器
KLOGG:专业开发者的海量日志分析利器 【免费下载链接】klogg Really fast log explorer based on glogg project 项目地址: https://gitcode.com/gh_mirrors/kl/klogg 你是否曾为在数十GB的日志文件中寻找关键错误信息而头痛不已?面对海量日志数据…...
仅0.3%用户掌握的胶片叙事技巧:用Midjourney实现“过期胶卷”时间衰减效果(含Exif元数据欺骗指令集)
更多请点击: https://intelliparadigm.com 第一章:胶片叙事与数字时代的时间诗学 胶片影像的物理性——帧率、显影时长、机械快门延时——曾将时间锚定为可触摸的物质存在;而数字媒介则以纳秒级采样、无损复制与非线性剪辑,将时间…...
内容创作平台集成多个AI模型提升内容多样性的实践
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 内容创作平台集成多个AI模型提升内容多样性的实践 对于内容创作平台而言,用户的偏好千差万别,内容的类型也…...
League Akari:英雄联盟玩家的智能游戏助手
League Akari:英雄联盟玩家的智能游戏助手 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power 🚀. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 你是否厌倦了在英雄联盟中重复繁琐的准备…...
SAP ECC6 2027年停服倒计时:手把手教你评估四大迁移路径与成本(含第三方支持避坑指南)
SAP ECC6 2027年停服倒计时:企业迁移决策全景指南 当2027年的钟声敲响时,全球仍在运行SAP ECC6系统的企业将面临一个关键转折点。这不是简单的技术升级,而是一次关乎企业数字化未来的战略抉择。作为经历过三次SAP重大版本迁移的顾问ÿ…...
如何快速上手专业3D点云标注工具:完整入门指南
如何快速上手专业3D点云标注工具:完整入门指南 【免费下载链接】labelCloud A lightweight tool for labeling 3D bounding boxes in point clouds. 项目地址: https://gitcode.com/gh_mirrors/la/labelCloud 在自动驾驶、机器人视觉和三维重建等领域&#x…...
从动态规划到最优策略:基于模型的强化学习核心算法剖析
1. 从动态规划到强化学习的桥梁 动态规划(Dynamic Programming,DP)是解决序列决策问题的经典方法,而强化学习(Reinforcement Learning,RL)则可以看作是在未知环境下的动态规划。我第一次接触这个…...
如何快速掌握LiteDB.Studio:面向初学者的LiteDB数据库终极GUI管理工具完整指南
如何快速掌握LiteDB.Studio:面向初学者的LiteDB数据库终极GUI管理工具完整指南 【免费下载链接】LiteDB.Studio A GUI tool for viewing and editing documents for LiteDB v5 项目地址: https://gitcode.com/gh_mirrors/li/LiteDB.Studio 在嵌入式数据库应用…...
