这里
按GC拥有对象构造类对象来,写这些.
准则:
论坛中看到了以下几个观点.
1,(这是复杂问题.)类没有析构器;应该叫终结者.
2,不要在类析构器中从GC分配内存.(如,writeln可能适合简单类型,但writefln或format则不行.)
3,因为可能已析构,不要使用类析构器中GC拥有成员.
一些事实:
1,不保证执行类析构器.这是程序员无法控制的.如,用户可传递以下命令行选项,而GC不会执行类析构器:
$ myprogram "--DRT-gcopt=cleanup:none" ...(这样启动时,以下示例运行良好.)
2,即使GC执行了析构器的,也不知道何时准确执行.因此,重要任务交给类析构器(如关闭文件)是不行的.
恐怖:
我刚刚发现一个大问题.
上面两个准则(“不要使用类成员"和"不要分配”)错过重要的事实,对类结构成员也要递归这样.如,作为类成员的结构也不能在析构器中分配内存.
以下程序以core.exception.InvalidMemoryOperationError结束:
import std.format;
void closeConnection(string s) {
}
struct S {
int id;
~this() {
closeConnection(format!"%s关闭"(id));
}
}
class C {
S s;//类中构
this(int id) {
s = S(id);
}
// @disable ~this();//应禁止
}
void main() {
//只需1就可`显示`阿里环境下错误.
enum N = 1;
foreach (i; 0 .. N) {
auto c = new C(i);
}
}问题在遗漏的指导方针:类应该@disable析构器.取消注释该行时,上面程序正常工作.
当然,应该加上@disable ~this();作为行为准则.
你怎么看?
不.类析构器用于清理非垃集资源.只要坚持这点,就可安全运行它们.
放入类的结构必须正确运行析构器,否则,会遇见可怕的不一致.
如,我不想在类中禁止RefCounted结构的析构.
如果关心在构 析构器中使用垃集,可用GC.inFinalizer检查.
我记得几年前,Andrei提议从语言中完全删除类析构器(或终结器,等等).有点极端,但反映了你的一般想法.
关于类析构器的一个观察是,如果不能清理资源(运行中不能依赖它,且禁止使用可能已收集的类引用),则*它们有何实际用途*,就没用.
类析构器的默认版无用,非默认时有用.
因此,如果用户使用--DRT-gcopt=cleanup:none运行程序,碰巧在GC分配类中有个RefCounted结构,则搞砸了?
便宜方法是使用像sprintf这样的@nogc方法?
:唔.也许准则应该是"析构器必须是@nogc".
我同意.
可观察到:
a),对所有类@disable ~this(),这样可免受其他编写良好结构成员析构器影响.一般,此选项需要该类的应在释放垃集内存前调用的清理函数.
b),在每个有可能在类中使用的构析构器中考虑GC.inFinalizer()(不一定都适用).
c),构中也不要在析构器中分配垃集内存.
struct S {
int id;
string closingMessage; // <-- 很贵
this(int id) {
this.id = id;
this.closingMessage = format!"%s关闭"(id);
}
~this() {
// 这里不分配,很好.
closeConnection(closingMessage);
}
}用@nogc,如sprintf很便宜.










