d必须禁止析构器吗

这里
GC拥有对象构造类对象来,写这些.
准则:
论坛中看到了以下几个观点.
1,(这是复杂问题.)类没有析构器;应该叫终结者.
2,不要在类析构器中从GC分配内存.(如,writeln可能适合简单类型,但writeflnformat则不行.)
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很便宜.

posted @   zjh6  阅读(10)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示