欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > Mojo值的生命周期(Death of a value)详解

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

2024/10/24 9:20:09 来源:https://blog.csdn.net/j610152753/article/details/140890003  浏览:    关键词:Mojo值的生命周期(Death of a value)详解

一旦不再使用某个值/对象,Mojo 就会将其销毁。Mojo 不会等到 代码块结束(甚至不会等到表达式结束)才销毁未使用的值。它使用在每个子表达式之后运行的“尽快”(ASAP)销毁策略来销毁值。即使在像这样的表达式中a+b+c+d,Mojo 也会在不再需要中间值时立即销毁它们。

Mojo 使用静态编译器分析来查找值最后一次使用的位置。然后,Mojo 立即结束该值的生命周期并调用析__del__() 构函数来执行该类型的任何必要清理。

例如,请注意__del__()每个实例的析构函数被调用的时间MyPet:

@value
struct MyPet:var name: Stringvar age: Intfn __del__(owned self):print("Destruct", self.name)fn pets():var a = MyPet("Loki", 4)var b = MyPet("Sylvie", 2)print(a.name)# a.__del__() runs here for "Loki"a = MyPet("Charlie", 8)# a.__del__() runs immediately because "Charlie" is never usedprint(b.name)# b.__del__() runs herepets()

输出为:

Loki
Destruct Loki
Destruct Charlie
Sylvie
Destruct Sylvie

请注意,每个值的初始化都与对析构函数的调用相匹配,并且a实际上会被销毁多次 - 每次收到新值时都会销毁一次。

大多数结构不需要自定义析构函数,如果你没有定义析构函数,Mojo 会自动添加一个无操作析构函数。

默认销毁行为


您可能想知道 Mojo 如何在没有自定义析构函数的情况下销毁类型,或者为什么无操作析构函数很有用。如果类型只是字段的集合(如示例)MyPet,则 Mojo 只需销毁字段:MyPet不会动态分配内存或使用任何长期存在的资源(如文件句柄)。当值被销毁时,对于MyPet的销毁无需采取任何特殊操作。

查看各个字段,MyPet包括一个Int和String。

Mojo的Int称其为简单类型。它是静态大小位数。Mojo 确切知道它有多大,因此可以重复使用这些位来存储其他内容。

Mojo的String值稍微复杂一些。Mojo 字符串是可变的。该 String对象有一个内部缓冲区 - 一个 List字段,它保存组成字符串的字符。AList将其内容存储在堆上动态分配的内存中,因此字符串可以增大或缩小。字符串本身没有任何特殊的析构函数逻辑,但当 Mojo 销毁字符串时,它会调用该字段的析构函数 List,从而取消分配内存。

由于String和Int不需要任何自定义析构函数逻辑,它们都具有无操作析构函数:字面意思是__del__()不执行任何操作的方法。这似乎毫无意义,但这意味着 Mojo 可以在任何值的生命周期结束时调用其析构函数。这使得编写通用容器和算法变得更加容易。

ASAP 销毁的好处


与其他语言类似,Mojo 遵循对象/值在构造函数(init())中获取资源并在析构函数(del())中释放资源的原则。但是,Mojo 的 ASAP 销毁比基于范围的销毁具有一些优势(例如 C++ RAII 模式,它等到代码范围结束后才销毁值):

  • 最后一次使用时立即销毁值与“移动”优化完美结合,将“复制 + 删除”对转换为“移动”操作。
  • 在 C++ 中,在作用域末尾销毁值对于某些常见模式(如尾部递归)而言是有问题的,因为析构函数调用发生在尾部调用之后。对于某些函数式编程模式而言,这可能是一个严重的性能和内存问题,但在 Mojo 中则不是问题,因为析构函数调用始终发生在尾部调用之前。

此外,Mojo 的 ASAP 销毁在 Python 风格的def 函数中效果很好。这是因为 Python 实际上不提供超出函数范围的范围,因此 Python 垃圾收集器清理资源的频率比基于范围的销毁策略更高。但是,Mojo 不使用垃圾收集器,因此 ASAP 销毁策略提供的销毁保证比 Python 更细粒度。

Mojo 的销毁策略与 Rust 和 Swift 的工作方式更相似,因为它们都具有强大的值所有权跟踪功能并提供内存安全性。一个区别是 Rust 和 Swift 需要使用动态“删除标志” ——它们维护隐藏的影子变量来跟踪值的状态以提供安全性。这些通常会被优化掉,但 Mojo 方法完全消除了这种开销,

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com