在构造函数中初始化实例变量和从构造函数中初始化实例变量有什么区别?

What is the difference between initializing instance variables in & out of a constructor?

在下面的代码示例中,milk 由构造函数初始化,而 egg 不是。 milk.spill() 不会出现段错误,但 egg.crack() 会。初始化实例变量的两种方式有什么区别?为什么前者正确而后者导致段错误?

import std.stdio;

void main() {
  auto k = new Kitchen();
  k.pollute();
}

class Kitchen {
  Milk milk;
  Egg egg = new Egg();

  this() {
    milk = new Milk();
  }

  void pollute() {
    writeln("spilling milk");
    milk.spill();
    writeln("cracking egg");
    egg.crack();
  }
}

class Milk {
  bool spilt = false;
  void spill() { spilt = true; }
}

class Egg {
  bool cracked = false;
  void crack() { cracked = true; }
}

所以这两种方式的区别在于代码是运行的时候。当您在构造函数中进行初始化时,代码是 运行 在 运行 时间,即创建每个新对象时。当您直接在 class 成员上执行时,该对象实际上是在编译时构造并静态引用的。

在您的示例中,这意味着为每个 Kitchen 对象创建了一个新的 Milk 对象。当你 运行 new Kitchen 时,构造函数 运行s,意味着你也得到了 new Milk

Egg不一样。它处于静态上下文中,因此初始化程序在编译时为 运行 - 只有一次。这意味着只有 一个 Egg 在所有 new Kitchen 之间共享。变量本身不是静态的,如果你在创建 new Kitchen 之后的某个时间将它分配给 new Egg,它只会影响厨房的那个实例,但它引用的对象会立即 .

因此,如果您只是在构造函数之外将它设置为 new Egg 并且从不替换它,那么您对该鸡蛋所做的任何修改都将在厨房的所有实例中可见 - 在您打碎鸡蛋之后,然后执行另一个new Kitchen,它已经有一个破蛋了!