March 25, 2019
On Monday, 25 March 2019 at 18:21:12 UTC, Meta wrote:
> Ouch, you're right.
>
> import std.array: Appender;
>
> class Class
> {
>     Appender!(int[]) app = null;
> }
>
> void testAppender(Class c)
> {
>     import std.stdio;
>     writeln(c.app.data);
>     c.app ~= 10;
>     writeln(c.app.data);
> }
>
> void main()
> {
>     auto c1 = new Class();
>     auto c2 = new Class();
>     testAppender(c1);  //Prints [] and [10]
>     testAppender(c2); //Prints [10] and [10, 10]
> }
>
> I find that a bit strange, since you'd think that Appender would initialize its payload on the first append; and it seems like it does if you look at the code (in Appender.ensureAddable). I'm not sure how it shakes out that the two Appenders end up sharing the same memory.

Yep, that's correct. If you look at the AST analysis in run.dlang, what ends up happening is the constructor for Appender is evaluated statically as a side effect of "= null" becoming "= Appender(null)" and produces a static initializer referencing a shared global payload.
March 25, 2019
On Mon, Mar 25, 2019 at 4:00 PM FeepingCreature via Digitalmars-d < digitalmars-d@puremagic.com> wrote:

> class Class
> {
>      Appender!(int[]) app = null;
> }
>
> This is the most evil bug I've seen this year yet.
>
> Hint: Appender is a struct, not a class. So what does "= null" do, when it appears as a default initializer?
>
>
Yeah I remember this bug. But to be honest I believe it is already fixed,
but few days ago I still write something like this to be sure:
class Class
{
     Appender!(int[]) app;

    this()
    {
        app = appender!(int[]);
    }
}


1 2
Next ›   Last »