当前位置:   article > 正文

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

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

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

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

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

@value
struct MyPet:
    var name: String
    var age: Int

    fn __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 used

    print(b.name)
    # b.__del__() runs here

pets()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

输出为:

Loki
Destruct Loki
Destruct Charlie
Sylvie
Destruct Sylvie
  • 1
  • 2
  • 3
  • 4
  • 5

请注意,每个值的初始化都与对析构函数的调用相匹配,并且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 方法完全消除了这种开销,

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/940479
推荐阅读
相关标签
  

闽ICP备14008679号