Why does reverse also flips my other dynamic array?

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Sep 13 18:12:41 PDT 2015


On Sunday, September 13, 2015 17:17:01 Ali Çehreli via Digitalmars-d-learn wrote:
> On 09/13/2015 08:21 AM, Jonathan M Davis via Digitalmars-d-learn wrote:
>  > On Saturday, September 12, 2015 14:59:23 Ali Çehreli via
> Digitalmars-d-learn wrote:
>  >> On 09/12/2015 02:29 PM, Marco Leise wrote:
>  >>
>  >>   > Note that often the original dynamic array has additional
>  >>   > capacity beyond its length. This can be used to ~= additional
>  >>   > items without causing a reallocation, but is lost when you
>  >>   > do the assignment "b = a".
>  >>
>  >> Actually, the capacity is still there, useful to the runtime.
>  >> Interestingly, the first dynamic array that is appended the new element
>  >> becomes the owner of that capacity. The capacity of the other dynamic
>  >> array becomes 0.
>  >>
>  >> import std.stdio;
>  >>
>  >> void main(){
>  >>
>  >>     int [] a = [1,2,3,4,5];
>  >>     int [] b = a;
>  >>
>  >>     writeln(a.ptr, " ", b.ptr);
>  >>     writeln(a.capacity, " ", b.capacity);
>  >>     a ~= 42;    // <-- change to b, now b owns the capacity
>  >>     writeln(a.ptr, " ", b.ptr);
>  >>     writeln(a.capacity, " ", b.capacity);
>  >> }
>  >
>  > It's not really the case that the capacity is owned. There simply is no
>  > available memory passed the end of b, because what would be the next
> element
>  > in b if it were appended to is now the last element of a. It's the
> same boat
>  > you're in if you simply did
>  >
>  > int[] a = [1, 2, 3, 4, 5];
>  > int[] b = a[0 .. $ - 1];
>  >
>  > In both cases, there's no room for b to grow into, because a is using the
>  > space immediately after b.
>  >
>  > - Jonathan M Davis
>
> Thanks for clarifying. My point was about capacity not being lost;
> rather, being used (owned) by the _first_ slice that gets extended. If
> we append to 'a' first, then 'a' extends in place and 'b' gets
> relocated. If we append to 'b' first, then vice versa...

Yeah. Only dynamic arrays whose last element refers to the last element that
has been expanded into in a GC-allocated memory buffer can be appended to
without reallocating. If the memory block wasn't specifically allocated by
the GC for dynamic arrays, then there won't be any memory to expand into,
and even if it is a GC-allocated buffer for dynamic arrays (as is usually
the case), if another dynamic array has ever referred to any elements past
the end of the dynamic array you're looking at, then that dynamic array
can't be appended to without being reallocated, because it would potentially
stomp on another dynamic array. So, if you have multiple dynamic arrays
referring to the same memory, only one of them can expand into the unused
memory past their ends. Anything else would allow stomping.

The result of this is that if you're doing a lot of appending, you probably
don't want to be doing a lot of slicing unless the slices aren't being
appended to. It'll still work if they're appended to, but pretty quickly
it'll mean that most of the appending that you're doing is causing
reallocations, which could really harm performance.

- Jonathan M Davis




More information about the Digitalmars-d-learn mailing list