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

Mojo值的生命周期(Life of a value)详解

到目前为止,我们已经解释了 Mojo 如何允许您使用 Mojo 的所有权模型构建内存安全的高性能代码而无需手动管理内存。但是,Mojo 是为 系统编程而设计的,这通常需要对自定义数据类型进行手动内存管理。因此,Mojo 允许您根据需要执行此操作。需要明确的是,Mojo 没有引用计数器和垃圾收集器。
Mojo 也没有具有特殊权限的内置数据类型。标准库中的所有数据类型(例如Bool、 Int和 String)都以 结构体形式实现。您实际上可以使用MLIR 方言提供的低级原语编写自己的这些类型的替代品 。

Mojo 语言的优点在于它为您提供了这些用于系统编程的低级工具,但在一个框架内,可以帮助您构建安全且易于从高级程序使用的东西。也就是说,您可以深入底层并编写您想要的所有“不安全”代码,但只要您按照 Mojo 的值语义进行操作,实例化您的类型/对象的程序员根本不需要考虑内存管理,而且由于值所有权,行为将是安全且可预测的。

总之,类型作者有责任管理每个值​​类型的内存和资源,方法是根据需要实现特定的生命周期方法,例如构造函数、复制构造函数、移动构造函数和析构函数。Mojo 默认不创建任何构造函数,但它确实为未定义自己的类型添加了一个简单的无操作析构函数。

接下来,我们将准确解释如何根据值语义定义这些生命周期方法,以便您的类型能够很好地与值所有权兼容。

生命周期和寿命(Lifecycles and lifetimes)


首先,让我们澄清一些术语:

  • 值的“生命周期”由结构中的各种dunder方法定义。每个生命周期事件都由不同的方法处理,例如构造函数(__init__())、析构函数(__del__()。所有使用相同类型声明的值都具有相同的生命周期。
  • 值的“生命周期”由程序执行期间每个值被视为有效的时间跨度定义。值的生命周期从初始化时开始,到销毁时结束,通常(但并非总是)从__init__()到__del__()。没有两个值具有完全相同的生命周期,因为每个值都是在不同的时间点创建和销毁的(即使差异是不可感知的)。

Mojo 中值的生命周期始于变量初始化时,一直持续到最后一次使用该值,此时 Mojo 会将其销毁。Mojo 会在不再使用每个值/对象时立即销毁它,使用在每个子表达式之后运行的“尽快”(ASAP) 销毁策略。

您可能可以想象,如果在程序的生命周期中,某个值在多个函数之间多次共享,那么跟踪该值的生命周期可能会很困难。但是,Mojo 通过其值语义和值所有权部分地使这一点变得可预测。生命周期管理的最后一块拼图是值的生命周期:每个值(在结构中定义)都需要实现关键的生命周期方法,这些方法定义了如何创建和销毁值。

值的生命周期(Life of a value)


Mojo 中值的生命周期始于变量初始化时,一直持续到最后一次使用该值,此时 Mojo 会将其销毁。

Mojo 中的所有数据类型(包括标准库中的基本类型,例如 Bool、 Int和 String,以及复杂类型,例如SIMD和 object)都定义为 struct。这意味着任何数据的创建和销毁都遵循相同的生命周期规则,并且您可以定义自己的数据类型,其工作方式完全相同。

Mojo 结构没有任何默认的生命周期方法,例如构造函数、复制构造函数或移动构造函数。这意味着您可以在没有构造函数的情况下创建结构,但您无法实例化它,并且它只能用作静态方法的一种命名空间。例如:

struct NoInstances:var state: Int@staticmethodfn print_hello():print("Hello world!")

如果没有构造函数,则无法实例化 this,因此它没有生命周期。该 state字段也是无用的,因为它无法初始化(Mojo 结构不支持默认字段值 - 只有必须在构造函数中初始化它们)。

NoInstances.print_hello()

输出:

Hello world!

以下代码无法通过编译。

   print(NoInstances.state) #cannot access instance field 'state' without an instance of 'NoInstances'

构造函数


要创建 Mojo 类型的实例,需要__init__()构造函数方法。构造函数的主要职责是初始化所有字段。例如:

struct MyPet:var name: Stringvar age: Intfn __init__(inout self, name: String, age: Int):self.name = nameself.age = age

现在我们可以创建一个实例:

var mine = MyPet("Loki", 4)

的实例MyPet也可以被 borrowed 和 destroyed,但目前不能被复制或移动。

我们认为这是一个很好的默认起点,因为没有内置的生命周期事件,也没有意外行为。您(类型作者)必须通过实现复制和移动构造函数来明确决定是否可以复制或移动类型以及如何复制或移动类型。

Mojo 不需要析构函数来销毁对象。只要结构中的所有字段都是可销毁的(标准库中的每个类型都是可销毁的, 指针除外),那么 Mojo 就知道如何在其生命周期结束时销毁该类型。我们将在值的消亡中进一步讨论这一点。

重载构造函数


与其他函数/方法一样,您可以 重载构造函数 __init__()以使用不同的参数初始化对象。例如,您可能需要一个默认构造函数来设置一些默认值并且不接受任何参数,然后需要接受更多参数的附加构造函数。

请注意,为了修改任何字段,每个构造函数都必须使用inout约定声明self参数。如果要从另一个构造函数调用一个构造函数,只需像在外部调用一样调用该构造函数(无需传递self)

例如,下面是如何从重载构造函数委托工作的方法:

struct MyPet:var name: Stringvar age: Intfn __init__(inout self):self.name = ""self.age = 0fn __init__(inout self, name: String):self = MyPet()self.name = name

字段初始化


请注意,在上例中,每个构造函数结束时,所有字段都必须初始化。这是构造函数中唯一的要求。

事实上,只要所有字段都已初始化,__init__()构造函数就足够聪明,甚至在构造函数完成之前就将self对象视为已完全初始化。例如,一旦所有字段都初始化,此构造函数就可以传递self:

fn use(arg: MyPet):passstruct MyPet:var name: Stringvar age: Intfn __init__(inout self, name: String, age: Int, cond: Bool):self.name = nameif cond:self.age = ageuse(self)  # Safe to use immediately!self.age = ageuse(self)  # Safe to use immediately!

下面的初始化会报错

struct MyPet:var name: Stringvar age: Intfn __init__(inout self, name

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Python酷库之旅-第三方库Pandas(062)
  • 【WPF开发】安装环境、新建工程
  • 一文读懂SEnet:如何让机器学习模型学会“重点观察”
  • 【Hadoop-驯化】一文教你轻松搞懂hadoop的基本原理
  • 单个或两个及以上java安装与环境变量配置
  • Java码农人生使用手册——类和对象
  • Python教程(十一):单元测试与异常捕获
  • CTFHub XSS DOM 跳转
  • Python面试整理-第三方库
  • C++面向对象高级编程(I)侯捷 自我总结版
  • vim、sublime、notepad文本编辑器的使用
  • 爬虫中常见的加密算法Base64伪加密,MD5加密【DES/AES/RSA/SHA/HMAC】及其代码实现(二)
  • 设计模式介绍
  • 测试面试宝典(四十二)—— 接口测试什么时候介入
  • thinkphp 关联查询例子
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • 【Under-the-hood-ReactJS-Part0】React源码解读
  • 【附node操作实例】redis简明入门系列—字符串类型
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • 【跃迁之路】【641天】程序员高效学习方法论探索系列(实验阶段398-2018.11.14)...
  • 345-反转字符串中的元音字母
  • CODING 缺陷管理功能正式开始公测
  • Django 博客开发教程 16 - 统计文章阅读量
  • FineReport中如何实现自动滚屏效果
  • go append函数以及写入
  • IDEA常用插件整理
  • JAVA并发编程--1.基础概念
  • js继承的实现方法
  • Laravel 菜鸟晋级之路
  • ng6--错误信息小结(持续更新)
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • React中的“虫洞”——Context
  • Spring框架之我见(三)——IOC、AOP
  • Sublime Text 2/3 绑定Eclipse快捷键
  • UEditor初始化失败(实例已存在,但视图未渲染出来,单页化)
  • Webpack 4 学习01(基础配置)
  • windows下mongoDB的环境配置
  • 多线程事务回滚
  • 判断客户端类型,Android,iOS,PC
  • 提醒我喝水chrome插件开发指南
  • 推荐一个React的管理后台框架
  • 学习Vue.js的五个小例子
  • 要让cordova项目适配iphoneX + ios11.4,总共要几步?三步
  • 在Unity中实现一个简单的消息管理器
  • 最简单的无缝轮播
  • ​【C语言】长篇详解,字符系列篇3-----strstr,strtok,strerror字符串函数的使用【图文详解​】
  • #pragma once与条件编译
  • (2)nginx 安装、启停
  • (vue)页面文件上传获取:action地址
  • (zt)最盛行的警世狂言(爆笑)
  • (二十三)Flask之高频面试点
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (利用IDEA+Maven)定制属于自己的jar包
  • (排序详解之 堆排序)
  • (十五)devops持续集成开发——jenkins流水线构建策略配置及触发器的使用