Why do immutable variables need reference counting?

Paul Backus snarwin at gmail.com
Mon Apr 11 15:02:49 UTC 2022


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.


More information about the Digitalmars-d-learn mailing list