resizeable arrays: T[new]
Oskar Linde
oskar.lindeREM at OVEgmail.com
Sat Jun 9 11:15:58 PDT 2007
Bruno Medeiros skrev:
> Walter Bright wrote:
>> Sean Kelly wrote:
>>> Walter Bright wrote:
>>>> (The problem is if I pass a slice to a function, and then that
>>>> function reallocates the slice by changing the length or appending
>>>> to it, it can affect other slices into the same data in very
>>>> hard-to-explain ways.
>>>
>>> I'm not sure I understand how a reallocation could affect other
>>> slices into the same data. If a reallocation occurs, that
>>> reallocation will be into entirely new memory, provided the slice
>>> doesn't start at the head of a memory block. Is it the condition I
>>> just mentioned that's a problem? If so, I suppose it is one way to
>>> trick the compiler into thinking the reference no longer refers to
>>> const data, when in fact it does. If not, could you point me in the
>>> right direction?
>>
>> Given:
>>
>> int[] a = new int[7];
>> int[] b = a[1..6];
>> b[1] = 2; // writes through to a[2]
>> b.length = 4;
>> b[1] = 3; // writes through to a[2]
>> b.length = 6;
>> b[1] = 4; // does not write through to a[2]
>>
>
> So, is that the problem we are trying to solve? Why not just simply make
> it so that setting .length *allways* creates a new array?
Not really an option. That would make ~= O(n^2) instead of O(n).
> Hum, now that I think about it, this may not only be a better solution,
> it may be the *only* real solution. Even, with the new
> resizable/unresizable array proposal you can have the same problem as
> above:
>
> int[new] a = new int[7];
> int[new] b = a;
> b.length = 6;
>
> b[1] = 2; // writes through to a[1]
> b.length = 4;
> b[1] = 3; // writes through to a[1]
> b.length = 10;
> b[1] = 4; // does not write through to a[1]
>
> Why does this problem exist? Because, setting an array length may or may
> not create a new array, and there isn't a way to know which will happen.
> Well, in that code segment we can see when it will resize, but we can't
> know in the general case (like when we receive an array as a function
> parameter). This makes setting .length as very unsafe operation, if not
> plain *broken*.
That's why my suggestion was making T[new] a reference type instead of a
value type, just like T[U] has become.
The associative array used to have a similar issue. Previously (before D
0.151):
int[int] a = ...;
int[int] b = a;
b[0] = 0;
could potentially corrupt a...
And an analogue for todays dynamic array:
int[] a = ...;
int[] b = a;
b.length = 1;
b ~= ...;
will corrupt a.
The solution would be identical: Make the resizable array a reference
type. Todays value type behavior for dynamic arrays are perfect for
slices, just not for resizable arrays.
Another option, if one wishes to resolve the above issues and have
T[new] remain a value type, would be to insert an implicit .dup on
assignment for T[new]. That way, there would never be two resizable
arrays sharing the same ptr.
/Oskar
More information about the Digitalmars-d-announce
mailing list