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