当前位置: 首页 > news >正文

Mojo中值的所有权简介

没有数据,程序就什么都不是,所有现代编程语言都将数据存储在两个地方之一:调用堆栈和堆(有时也存储在 CPU 寄存器中,但我们不会在这里讨论)。但是,每种语言读取和写入数据的方式略有不同——有时非常不同。因此,在以下部分中,我们将解释 Mojo 如何管理程序中的内存以及这会如何影响您编写 Mojo 代码的方式。

栈(Stack)和堆(Heap)概览


一般而言,所有编程语言使用调用堆栈的方式都相同:当调用一个函数时,编译器会在堆栈上分配一块内存,该内存的大小正好是存储执行逻辑和固定大小的 本地值所需的大小。当调用另一个函数时,其数据同样会添加到堆栈顶部。当一个函数完成时,堆栈中的所有数据都会被销毁,以便其他代码可以使用内存。

请注意,我们说过只有“固定大小的本地值”存储在堆栈中。动态大小的值可以在运行时改变大小,而是存储在堆中,堆是一块更大的内存区域,允许在运行时进行动态内存访问。从技术上讲,这种值的本地变量仍然存储在调用堆栈中,但其值是指向堆上实际值的固定大小指针。

此外,需要比函数的生命周期更长的值(例如在函数之间传递且不应复制的数组)存储在堆中,因为堆内存可以从调用堆栈中的任何位置访问,即使创建它的函数已从堆栈中删除。这种情况(堆分配的值被多个函数使用)是大多数内存错误发生的地方,也是不同编程语言的内存管理策略差异最大的地方。

内存管理策略


由于内存有限,因此程序必须尽快从堆中删除未使用的数据(“释放”内存)。确定何时释放该内存非常复杂。

一些编程语言试图利用“垃圾收集器”进程来隐藏内存管理的复杂性,该进程跟踪所有内存使用情况并定期释放未使用的堆内存(也称为自动内存管理)。这种方法的一个显著好处是它减轻了开发人员手动内存管理的负担,通常可以避免更多错误并提高开发人员的工作效率。然而,它会产生性能成本,因为垃圾收集器会中断程序的执行,并且可能无法很快回收内存。

其他语言要求您手动释放堆上分配的数据。如果操作正确,这将使程序执行得更快,因为垃圾收集器不会消耗任何处理时间。然而,这种方法的挑战在于程序员会犯错误,尤其是当程序的多个部分需要访问同一内存时——很难知道程序的哪个部分“拥有”数据并必须释放它。程序员可能会在程序完成之前意外释放数据(导致“释放后使用”错误),或者他们可能会释放两次数据(“双重释放”错误),或者他们可能永远不会释放数据(“泄漏内存”错误)。诸如此类的错误可能会给程序带来灾难性的后果,而且这些错误通常很难追踪,因此,从一开始就避免发生它们就显得尤为重要。

Mojo 使用第三种方法,称为“所有权”,该方法依赖于程序员在传递值时必须遵循的一组规则。这些规则确保每个内存块一次只有一个“所有者”,并且内存会相应地释放。通过这种方式,Mojo 会自动为您分配和释放堆内存,但它以一种确定性的方式进行,并且不会出现诸如释放后使用、双重释放和内存泄漏等错误。此外,它这样做的性能开销非常低。

Mojo 的价值所有权模型在编程效率和强大的内存安全性之间实现了完美平衡。它只需要您学习一些新语法和一些有关如何在程序中共享内存访问的规则。

但在我们解释 Mojo 的值所有权模型的规则和语法之前,您首先需要了解值语义。

值语义


Mojo 不强制执行值语义或引用语义。它支持这两种语义,并允许每种类型定义其创建、复制和移动的方式(如果有的话)。因此,如果您正在构建自己的类型,则可以实现它以支持值语义、引用语义或两者兼而有之。也就是说,Mojo 的设计参数行为默认为值语义,并且它为引用语义提供了严格的控制,以避免内存错误。

值所有权模型提供了对引用语义的控制,但在我们讨论其语法和规则之前,重要的是要了解值语义的原理。一般来说,这意味着每个变量对一个值都有唯一的访问权限,并且该变量范围之外的任何代码都不能修改其值。

值语义介绍


在最基本的情况下,共享值语义类型意味着您创建了该值的副本。这也称为“按值传递”。例如,请参考以下代码:

x = 1
y = x
y += 1print(x)
print

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 区块链的搭建和运维4
  • 数据可视化Axure大屏原型制作分享
  • CAN 应用编程基础-I.MX6U嵌入式Linux C应用编程学习笔记基于正点原子阿尔法开发板
  • 华为OD-D卷找座位
  • 计算机毕业设计选题推荐-生活垃圾治理系统-Java/Python项目实战
  • 苹果应用程序清理卸载工具:App Cleaner Uninstaller Pro for Mac
  • Python设计模式 - 抽象工厂模式
  • Java学习Day20
  • RabbitMQ、Kafka对比(超详细),Kafka、RabbitMQ、RocketMQ的区别
  • 接口自动化测试框架中动态参数接口,加密接口,签名接口你们是怎么处理的?
  • TCP如何建立长连接
  • Jar工具完全指南:从入门到精通
  • C语言学习——函数
  • MySQL常用的日期和时间函数
  • oracle 比较两个值取小使用LEAST函数
  • [deviceone开发]-do_Webview的基本示例
  • centos安装java运行环境jdk+tomcat
  • classpath对获取配置文件的影响
  • iOS高仿微信项目、阴影圆角渐变色效果、卡片动画、波浪动画、路由框架等源码...
  • Laravel Mix运行时关于es2015报错解决方案
  • Laravel 实践之路: 数据库迁移与数据填充
  • Node + FFmpeg 实现Canvas动画导出视频
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 技术胖1-4季视频复习— (看视频笔记)
  • 浏览器缓存机制分析
  • 视频flv转mp4最快的几种方法(就是不用格式工厂)
  • 我看到的前端
  • 正则表达式小结
  • Spring Batch JSON 支持
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • ​渐进式Web应用PWA的未来
  • ( 10 )MySQL中的外键
  • (C语言)编写程序将一个4×4的数组进行顺时针旋转90度后输出。
  • (rabbitmq的高级特性)消息可靠性
  • (力扣题库)跳跃游戏II(c++)
  • (每日一问)操作系统:常见的 Linux 指令详解
  • (三)uboot源码分析
  • (十七)devops持续集成开发——使用jenkins流水线pipeline方式发布一个微服务项目
  • (图文详解)小程序AppID申请以及在Hbuilderx中运行
  • (五)网络优化与超参数选择--九五小庞
  • (学习日记)2024.04.10:UCOSIII第三十八节:事件实验
  • (转)3D模板阴影原理
  • (转)为C# Windows服务添加安装程序
  • .h头文件 .lib动态链接库文件 .dll 动态链接库
  • .Net 6.0 处理跨域的方式
  • .NET 使用配置文件
  • .NET 应用架构指导 V2 学习笔记(一) 软件架构的关键原则
  • .NET国产化改造探索(一)、VMware安装银河麒麟
  • .net使用excel的cells对象没有value方法——学习.net的Excel工作表问题
  • .Net转Java自学之路—SpringMVC框架篇六(异常处理)
  • .pop ----remove 删除
  • /dev/sda2 is mounted; will not make a filesystem here!
  • ??在JSP中,java和JavaScript如何交互?
  • @select 怎么写存储过程_你知道select语句和update语句分别是怎么执行的吗?
  • [<MySQL优化总结>]