On Monday, 11 April 2022 at 12:12:39 UTC, Salih Dincer wrote:
It worked for me in a different way.

1 is (about to be) alive!
2 is (already) dead.
2 is (already) dead.
2 is (already) dead.

2 is (already) dead.
2 is (already) dead.
Hello D!
1 is (already) dead.

Because I changed the code like this.

```d

struct S
{
  . . .

  string toString() { return ""; }
}

//S test(inout S s)/*
S test(S s)//*/
{
  s.i = 2;
  return s;
}

void main()
{
  immutable s = S(1);
  test(s).writeln;
  "Hello".writefln!"%s D!";
}
```

If the inout is set, it does not allow compilation.

Because `S` does not contain any pointers or references, you are allowed to create a mutable *copy* of an `S` from an `immutable` source. That's what happens when you pass it to `test`.

The extra destructor calls come from the copies made by `test` and `writeln`. If you add a copy constructor, you can see this happening in the output:

```d
struct S {

    /* ... */

    this(ref inout typeof(this) other) inout {
        this.i = other.i;
        writeln(i, " was copied.");
    }
}
```

```
1 is (about to be) alive!
1 was copied.
2 was copied.
2 is (already) dead.
2 was copied.
2 was copied.
2 was copied.
2 is (already) dead.
2 is (already) dead.

2 is (already) dead.
2 is (already) dead.
Hello D!
1 is (already) dead.
```

1 constructor call + 5 copies = 6 destructor calls.

Reply via email to