使用 writeln 打印结构时额外的 null

Extra null when a struct is printed with writeln

在下面的代码中,当使用 writeln 打印 S2 的实例时,输出中额外的 null 是什么?

$ dmd -de -w so_004.d && ./so_004
S1("A", 1)
S2("A", 1, null)

如果我在包范围内定义 S2(即在 main 函数之外),null 就会消失。

使用合理的最新 DMD 编译:

$ dmd --version
DMD64 D Compiler v2.083.0
Copyright (C) 1999-2018 by The D Language Foundation, All Rights Reserved written by Walter Bright

我在学习 opEquals 时注意到了这个问题,我不打算在 "real" 代码中定义子范围中的类型。

import std.stdio;

void main() {
  {
    struct S1 { string id; ushort x; }
    auto a = S1("A", 1);
    assert(a == a);
    writeln(a);
  }

  {
    struct S2 {
      string id; ushort x;
      bool opEquals()(auto ref const string rhs) const {
        return id == rhs;
      }
    }

    auto a = S2("A", 1);
    assert(a == "A");
    writeln(a);
  }
}

它是上下文指针(在S2.tupleof中称为this),指的是在其上创建S2实例的堆栈帧。这通常会在这样的代码中使用:

auto fun(int n) {
    struct S {
        int get() { return n; }
    }
    return S();
}

上面的代码会在堆上分配 n,并在 Sthis 成员中放置一个指向它的指针。

现在,至于为什么它在您的代码中 - that's a bug。不需要上下文指针,因为该结构没有使用其范围内的任何变量。要删除它,只需将 S2 标记为 static:

static struct S2 {
    string id; ushort x;
    bool opEquals()(auto ref const string rhs) const {
        return id == rhs;
    }
}

auto a = S2("A", 1);
writeln(a); // S2("A", 1)