classdinitializerdmd

Are initializer expressions part of the constructor in D?


In D, can I initialize directly on declaration and expect the initializer expressions are part of the constructor? I came from C# and there this is the case. But with DMD 2.071.0 Im getting other behavior.

class Other { }

class Test { Other nonStaticMember = new Other; }

void test()
{
    auto t1 = new Test;
    auto t2 = new Test;
    // Assert is failing, the two Test instances are 
    // being initialized to the same reference
    // instead of execute the Other constructor twice.
    assert(t1.nonStaticMember !is t2.nonStaticMember);
}

If this is the intented behavior it should be documented here: https://dlang.org/spec/class.html right?


Solution

  • This code doesn't do in D what it would do in C#.

    In your example, Other is instantiated during compilation.

    I.e. Other is instantiated once, during compilation, and is placed in the program's data segment. Then, nonStaticMember's initial value will, by default, point to that instance of Other, for all Test instances.

    So, everything is working exactly as designed, even if it may be surprising when coming from other languages.

    If this is the intented behavior it should be documented here: https://dlang.org/spec/class.html right?

    Perhaps, but note that this behavior is not at all specific to classes. A pointer to any value allocated on the heap, as the initial value of a global or local static variable, will behave the same. Whenever the value of an expression is demanded during compilation (and that includes initializers for global/static variables), D attempts to evaluate it at compile-time. A few years ago, this has been extended to allocating values on the "heap" too, which then end up in the program's initial data segment.