On Sunday, 19 October 2025 at 20:44:39 UTC, Brother Bill wrote:
But incrementing the length of tailSlice by 1 breaks sharing.
This is unexpected.

This is not really unexpected.
It's easier to think about it if you treat slices as structs with 2 members, a pointer and a length. The important member is the pointer.

```d
int[] slice = [1, 3, 5, 7, 9, 11, 13, 15];
```

Here you create a "struct" with a pointer provided by the GC. The GC keeps track of the amount of items this pointer is pointing to. It's not really important how it is tracked. The safest assumption a user can make in any language is that the pointer owns the memory.

```d
int[] tailSlice = slice[$ / 2 .. $];
```

Here you create a new "struct" whose pointer differs from `slice`. The layout of the data now looks like this:

```
`slice` pointer    : ...*########...
`tailSlice` pointer: .......*####...
```

The pointer of `tailSlice` doesn't own the memory. It's a view into the memory owned by the `slice` pointer.

```
tailSlice.length += 1;
```

You are now changing the length of struct `tailSlice`. There is really no good way to know if the pointer of `tailSlice` is an item of `slice` or if the last item of `tailSlice` is the last item of `slice`, so the GC will copy the data to a new memory block and append one new item.

That's kinda it. If you try to append or remove items in cases like this, you will probably get a new pointer. If you want to use a slice as a dynamic array, it's a good idea to pass it by `ref` or pointer. Hope this helps.

Reply via email to