二-内存模型及所有权和引用、借用

1. 内存模型1

内存模型,heap和stack的区别,GC方面和go的区别

基本同go一样,分为堆内存、栈内存。栈内存函数退出时会自动释放,大小有限,一般是比较“小”的变量存到栈上。
比较“大”的或者大小动态变化的会分配到堆上。同时为了使用这个值,需要在栈上有一个变量指向这个堆的地址。
和go的区别在于,go是GC系统在运行时动态记录堆内存的使用情况,自己来清理,用户完全不用管。c这类完全交给用户处理,总是容易出错。
Rust介于两者之间,通过所有权和生命周期的机制,在编译阶段识别到堆内存的使用情况,等到不再被使用时,会自动清理。

2. String类型

整个高级点的东西,继续说明上面的内存问题,基于这种类型讲所有权、借用才有意义

这里的String类似go里面的字符切片,var stringSlice []byte,结构也类似,有一个结构体 包含指针、cap、len 三字表头,然后指针指向堆内存的一个 “底层数组”。
根据结构可知,既然涉及到堆内存,就关系到内存释放问题,对于Rust就是通过所有权和生命周期机制,“自动”释放内存。

使用示例如下:

// 注意 mut 声明的才可以继续进行修改操作
let mut string1 = String::from("String hello");
string1.push_str(", world");
println!("{}", string1);

3. 所有权,引用、可变引用、借用,

3.1 先看一个示例

fn main() {let mut s = String::from("Hello ");s.push_str("world");// 把s做为参数传给另一个函数,这个在go里很常见,会拷贝s的皮,但是用一套底层数组just_print(s); //  - value moved hereprintln!("{}", s);
}fn just_print(s: String) {// do some thingprintln!("{}", s);
}

这时学go同学惊呆了,后面s竟然是无效的了,感觉很不合理,明明有这个变量,竟然会无效;学c++的同学,可能联想到,如果这个指针,在最后一行打印之前,被Delete了,那的确会异常。
所以有GC语言的同学,如果接受不了,存在变量,但是无效的情况,可以结合C++想一下,这不就是写了个bug。

3.2 所有权转移

上文示例,其实就是所有权转移,Rust通过一个堆内的“对象”,只能有一个变量拥有它的所有权这种方式,就能很好的追踪何时可以自动GC,在编译的时候,追踪这个对象的所有权变量,以及这个变量的使用情况,就可以在不用的时候释放内存。

let string1 = String::from("a");
let string3 = string1; // 这里会发生所有权转移,此时string1就无效了 println!("{}", string1);报错。

这样的限制,避免一个堆内存被多个变量指向,一是写代码的人容易勿删导致悬垂引用,二是只有一份所有权的情况下,编译器就可以盯着有所有权的这个变量的生命周期的范围,从而知道啥时候到期进行自动GC

3.3 mut

先说说这个,这个其实比所有权 应用什么的简单很多,就是控制能不能修改而已。

通过示例可以知道,是不是可变的关键在于用let绑定或者传参的时候,有没有mut,和之前的那个变量是不是可变的无关。

// string3.push_str("afs"); // 这时不能
let mut string4 = string3;
string4.push_str("!!! change to mut.");
println!("{}", string4);

3.4 引用、可变引用、借用

所有权每次都要来回转移,只能转移到一个上面,很是麻烦,尤其是函数传参的情况,作为参数传进去之后,如果不再返回回来,编译器就认为这个堆内存的生命就到这了,就给GC了。
所以增加了引用的概念,让事情简单一些,也叫借用borrow,之前所有权转移叫 move。

let string4 = get_then_return(string4);// 这里甚至有整成了不可变的,所以mut相对随意,甚至如果所有的都加mut就和其他语言一样了,但是引用那里有限制。
println!("{}", string4);
let s = &string4;

可变引用又会导致数据竞争问题,

3.5 引用借用的关系

这两个词经常一起出现,后面看了Rust程序设计第二版才清楚。引用是对&这种方式的表述,借用则是表示了他真正的道理:所有借用,必须归还,即借用不会影响原有的生命周期,反而受原有变量的生命周期控制。
引用是一个用于指代另一个值的值,需要里面的数据时,可以解引用。这个在go语言中不存在,因为go只有值传递,没有引用传递。

fn main() {let a = 10;let ai = &a;assert_eq!(*ai, a);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/150372.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3 ref和reactive使用watch属性的方法和区别

在Vue 3中,您可以使用watch函数和watch选项来监视ref和reactive创建的响应式数据的变化。下面是它们的使用方法和区别: 使用方法: 使用ref和watch: import { ref, watch } from vue;const count ref(0);watch(count, (newVal,…

【算法挨揍日记】day28——413. 等差数列划分、978. 最长湍流子数组

413. 等差数列划分 413. 等差数列划分 题目描述: 如果一个数列 至少有三个元素 ,并且任意两个相邻元素之差相同,则称该数列为等差数列。 例如,[1,3,5,7,9]、[7,7,7,7] 和 [3,-1,-5,-9] 都是等差数列。 给你一个整数数组 nums…

【数据结构】邻接表与邻接矩阵的转换

一.基本思想 1.邻接矩阵转换为邻接表: 先设置一个空的邻接表,然后查找邻接矩阵的值不为零元素,找到后在邻接表的单链表对应位置加入表边节点。 2.邻接表转换为邻接矩阵: 在邻接表上顺序取出每个表边结点,将邻接矩阵…

【基础架构】part-1 高可用策略和知识点总结

​ 系统应该保持高可用性,以确保用户能够始终访问和使用系统。这可以通过设计冗余和容错机制来实现,如负载均衡、故障转移、备份和恢复策略等。 1.1、引入冗余 通过冗余架构设计,如使用多个服务器节点、多个数据中心或云区域,确…

gRPC博客【建设进度0%】

学习资料来源:https://grpc.io/

鸿蒙系统调研适配

写在前面: 以下内容基于我个人翻阅的官方资料以及自己的理解写的,可能存在认知和理解上的偏差,有些地方并不一定是对的,请谨慎对待,注意甄别! 一、鸿蒙OS是什么? 华为推出的多端统一平台&…

【Gateway】基于ruoyi-cloud-plus项目,gateway局部过滤器和过滤返回以及集成nacos

1.使用Gateway路由转发 1.1标题引入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency>1.2添加YML配置 spring:cloud:gateway:# 打印请求日志(自定义)…

链动2+1模式:创新营销引领白酒产业新潮流

在当今高度竞争的市场环境中&#xff0c;创新营销模式对于企业的发展至关重要。链动21模式作为一种独特的营销策略&#xff0c;将白酒产品与该模式相结合&#xff0c;充分发挥其优势&#xff0c;通过独特的身份晋升和奖励机制&#xff0c;快速建立销售渠道&#xff0c;提高用户…

C++基础从0到1入门编程(二)

系统学习C 方便自己日后复习&#xff0c;错误的地方希望积极指正 往期文章&#xff1a;C基础从0到1入门编程&#xff08;一&#xff09; 参考视频&#xff1a; 1.黑马程序员匠心之作|C教程从0到1入门编程,学习编程不再难 2.系统化学习C 1 函数指针和回调函数 如果把函数的地址…

【C语言.oj刷题】有序#整型矩阵元素查找##{思路+C源码}

目录 题目信息 题目分析&#xff1a; 法一&#xff1a; 遍历二维数组&#xff08;低效&#xff09; 思路 源码 局限性 法二&#xff1a; 对每一行二分查找&#xff08;有所提效&#xff09; 思路 源码 局限性 法三&#xff1a; 利用一切有利条件使用二分查找 思路 …

由两个独立的高增益运算放大器组成的运放芯片D258,可应用于音频信号处理系统上

D258是由两个独立的高增益运算放大器组成。可以是单电源工作&#xff0c;也可以是双电源工作,电源的电流消耗与电源电压大小无关。应用范围包括变频放大器、DC增益部件和所有常规运算放大电路。 主要特点&#xff1a; ● 可单电源或双电源 工作 ● 在一个封装内的两个经…

vue3项目安装eslint和prettier

【几乎最全/全网最长的 2 万 字】前端工程化完整流程&#xff1a;从头搭到尾&#xff08;vue3 vite qiankun docker tailwindcss iview......&#xff09;_前端工程化流程-CSDN博客 vue3tsvite项目中使用eslintprettierstylelinthusky指南 - 掘金 上面两篇文章相互结合操…

网络工程师网络配置经典例题(五)

1、配置SwitchA的单臂静态BFD特性 [SwitchA] bfd [SwitchA-bfd] quit [SwitchA] bfd 1 bind peer-ip 10.2.2.2 interface vlanif 10 source-ip 10.1.1.1 one-arm-echo [SwitchA-bfd-session-1] discriminator local 1 [SwitchA-bfd-session-1] min-echo-rx-interval 200 …

音视频项目—基于FFmpeg和SDL的音视频播放器解析(十三)

介绍 在本系列&#xff0c;我打算花大篇幅讲解我的 gitee 项目音视频播放器&#xff0c;在这个项目&#xff0c;您可以学到音视频解封装&#xff0c;解码&#xff0c;SDL渲染相关的知识。您对源代码感兴趣的话&#xff0c;请查看基于FFmpeg和SDL的音视频播放器 如果您不理解本…

解决:Error: Missing binding xxxxx\node_modules\node-sass\vendor\win32-x64-83\

一、具体报错 二、报错原因 这个错误是由于缺少 node-sass 模块的绑定文件引起的。 三、导致原因 3.1、环境发生了变化 3.2、安装过程出现问题 四、解决方法步骤&#xff1a; 4.1、重新构建 node-sass 模块 npm rebuild node-sass 4.2、清除缓存并重新安装依赖 npm c…

20231117在ubuntu20.04下使用ZIP命令压缩文件夹

20231117在ubuntu20.04下使用ZIP命令压缩文件夹 2023/11/17 17:01 百度搜索&#xff1a;Ubuntu zip 压缩 https://blog.51cto.com/u_64214/7641253 Ubuntu压缩文件夹zip命令 原创 chenglei1208 2023-09-28 17:21:58博主文章分类&#xff1a;LINUX 小工具 文章标签命令行压缩包U…

Google身份验证器Google Authenticator的java服务端实现

Google身份验证器Google Authenticator是谷歌推出的一款基于时间与哈希的一次性密码算法的两步验证软件令牌&#xff0c;此软件用于Google的认证服务。此项服务所使用的算法已列于RFC 6238和RFC 4226中。谷歌验证器上的动态密码按照时间或使用次数不断动态变化&#xff08;默认…

从CentOS向KeyarchOS操作系统的wordpress应用迁移实战

文章目录 从CentOS向KeyarchOS操作系统的wordpress应用迁移实战一、使用浪潮信息X2Keyarch迁移工具完成操作系统的迁移1.1 迁移前的验证1.2 执行迁移评估1.3 开始迁移1.4 验证迁移结果1.5 迁移后的验证 二、总结 从CentOS向KeyarchOS操作系统的wordpress应用迁移实战 CentOS是一…

Java-拼图小游戏

文章目录 main方法登录界面游戏主界面User类图片素材获取方式 基于Java实现的拼图小游戏&#xff0c;代码与图片素材来自b站up主黑马程序员的Java教学视频。 main方法 import ui.LoginJframe;public class App {public static void main(String[] args) {new LoginJframe(); …

Element UI 偶发性图标乱码问题

1. 问题如图所示 2. 原因&#xff1a;sass版本低 sass: 1.26.8 sass-loader: 8.0.2 3. 解决方法 (1) 提高sass版本 (2) 在vue.config.js中添加配置 css: {loaderOptions: {sass: {sassOptions: {outputStyle: expanded}}}},4. 遇到的问题 升级后打包&#xff0c;报错 Syntax…