2.26. 终结器

终结器是特殊函数,在两种情况下被调用:

delete 在数据类型上显式调用:

var f <- [1,2,3,4]
delete f

基于 Lambda 的迭代器或生成器被排序:

var src <- [1,2,3,4]
var gen <- generator<int&> capture (move(src)) ( $ {
    for ( w in src ) {
        yield w
    }
    return false
})
for ( t in gen ) {
    print("t = {t}\n")
}
// 在捕获的 src 版本上调用 Finalizer

默认情况下,终结器在子类型上递归调用。

如果内存模型允许释放,则标准终结器也会释放内存:

options persistent_heap = true

var src <- [1,2,3,4]
delete src                      // src 的内存将在此处释放

可以通过覆盖 finalize 函数来为任何类型的定义自定义终结器。 还允许使用通用自定义终结器:

struct Foo {
    a : int
}
def finalize ( var foo : Foo ) {
    print("we kill foo\n")
}
var f = Foo(a = 5)
delete f                    //在此处打印 'we kill foo'

2.26.1. 规则和实施细节

终结器遵循以下规则:

如果自定义的 finalize 可用,则调用它而不是默认的。

指针终结器扩展为在取消引用的指针上调用 finalize ,然后在结果上调用本机内存终结器:

var pf = new Foo
unsafe {
    delete pf
}

这扩展到:

def finalize ( var __this:Foo?& explicit -const ) {
    if ( __this != null ) {
        _::finalize(deref(__this))
        delete /*native*/ __this
        __this = null
    }
}

静态数组通常调用 finalize_dim ,它最终确定它的所有值:

var f : Foo[5]
delete f

这扩展到:

def builtin`finalize_dim ( var a:Foo aka TT[5] explicit ) {
    for ( aV in a ) {
        _::finalize(aV)
    }
}

动态数组一般调用 finalize ,它最终确定它的所有值:

var f : array<Foo>
delete f

这扩展到:

def builtin`finalize ( var a:array<Foo aka TT> explicit ) {
    for ( aV in a ) {
        _::finalize(aV)
    }
    __builtin_array_free(a,4,__context__)
}

表一般调用 finalize ,它最终确定它的所有值,但不完成它的键:

var f : table<string;Foo>
delete f

这扩展到:

def builtin`finalize ( var a:table<string aka TK;Foo aka TV> explicit ) {
    for ( aV in values(a) ) {
        _::finalize(aV)
    }
    __builtin_table_free(a,8,4,__context__)
}

为结构生成自定义终结器。批注为 @do_not_delete 的字段将被忽略。 memzero 在末尾清除结构内存:

struct Goo {
    a : Foo
    @do_not_delete b : array<int>
}

var g <- default<Goo>
delete g

这扩展到:

def finalize ( var __this:Goo explicit ) {
    _::finalize(__this.a)
    __::builtin`finalize(__this.b)
    memzero(__this)
}

元组的行为类似于结构。无法忽略单个字段:

var t : tuple<Foo; int>
delete t

这扩展到:

def finalize ( var __this:tuple<Foo;int> explicit -const ) {
    _::finalize(__this._0)
    memzero(__this)
}

变体的行为类似于 Tuples。仅最终确定当前在用的变体:

var t : variant<f:Foo; i:int; ai:array<int>>
delete t

这扩展到:

def finalize ( var __this:variant<f:Foo;i:int;ai:array<int>> explicit -const ) {
    if ( __this is f ) {
        _::finalize(__this.f)
    } else if (__this is ai) {
        __::builtin`finalize(__this.ai)
    }
    memzero(__this)
}

Lambda 和生成器的捕获结构已最终确定。 Lambda 也可以定义自定义终结器 (参阅 Lambdas).

类可以在类体中定义自定义终结器 (参阅 Classes).