Slices and Dynamic Arrays

Jonathan M Davis newsgroup.d at jmdavisprog.com
Sun Dec 31 14:24:40 UTC 2017


On Sunday, December 31, 2017 01:57:58 Tony via Digitalmars-d-learn wrote:
> On Friday, 29 December 2017 at 23:13:20 UTC, Jonathan M Davis
>
> wrote:
> > The term "slice" is a bit overused in D, meaning a variety of
> > things. It doesn't help that some folks dislike the official
> > terminology. In general, a slice is a contiguous group of
> > elements. A slice of memory would be a contiguous block of
> > memory. A dynamic array therefore refers to a slice of memory
> > and could be called a slice, but it's also the case that using
> > the slice operater on a container is called slicing - e.g.
> > rbt[] would give you a range over the container rbt, and that
> > range is a slice of the container, but it's not an array at all.
>
> For me, it is confusing to use "slice" and "dynamic array" as
> synonyms. My initial impression was that they must have different
> code underlying them, and different behavior. I would pick one or
> the other. It should be:
>
> D Arrays
>    - Static
>    - Dynamic
>
> or
>
> D Arrays
>     - Static
>     - Slice
>
>
> The DLang Tour has a section on Slices that says in bold "Slices
> and dynamic arrays are the same". I think that sentence deserves
> an explanation as to why there are two terms being utilized for
> the same thing. I would prefer that "slice" as a noun was used
> only for the time when a dynamic array was initialized from a
> slice of another array. Or better yet - slice was never used as a
> noun - only a verb or adjective: took a slice of array A to form
> a slice dynamic array B (or slice-intialized dynamic array B).
>
> D Arrays
>     - Static
>     - Dynamic
>        - Slice-Initialized Dynamic

All dynamic arrays are slices of memory. What changes is what memory they're
sliced from. There is no master dynamic array that controls the memory that
backs all of these dynamic arrays. They're the same whether they were
allocated via new or slices from a static array or sliced from pointers or
whatever. _All_ a dynamic array is a pointer and a length - e.g.

struct DynamicArray(T)
{
    size_t length;
    T* ptr;
}

It has no mechanism for managing memory or tracking who owns it. All of that
is handled by whatever allocated the memory in the first place. In most
cases, that's the GC, but it doesn't have to be. The dynamic array doesn't
even have a way to keep track of its capacity. All of that is handled by the
GC.

Yes, appending to a dynamic array or calling reserve on it can cause memory
to be allocated by the GC, but that's because the GC looks at the capacity
of the array (which it calculates based on extra stuff it keeps track of)
and sees whether it can increase the length of the array in place (which it
can do only if the array is backed by GC-allocated memory, and the capacity
is greater than its current length). The GC then may allocate a new block of
memory and copy the contents of the array to the new memory, and the runtime
will adjust the two members of the dynamic array so that they point to the
new block of memory, but the dynamic array itself does none of this - and it
all works exactly the same if the dynamic array is backed by
non-GC-allocated memory. It's just that the GC will determine that since
it's not backed by GC-allocated memory, its capacity is 0, and any operation
that would need to increase the length or capacity of the array will need to
reallocate (after which, the dynamic array will be backed by GC-allocated
memory regardless of what backed it before).

In no case does the dynamic array itself manage its own memory, and there is
no concept of the "original" dynamic array that the others come from. As
confusing as that may seem at first, that simply isn't how dynamic arrays in
D work. Rather than being a container which you can get ranges over, they're
a weird hybrid between the two. They have operations that act like they own
and manage their own memory, but they really don't.

The D Slices article does an excellent job of explaining all of this. It's
just that it calls the GC-allocated memory buffer the dynamic array instead
of calling T[] the dynamic array like the language and spec do. Regardless,
all non-null dynamic arrays are slices of memory.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list