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).