Thread overview
Question about dynamic arrays and slices
Jan 30, 2014
Ary Borenszweig
Jan 30, 2014
Tobias Pankrath
Jan 30, 2014
John Colvin
Jan 30, 2014
John Colvin
January 30, 2014
Hi,

I just read this nice article about slices: http://dlang.org/d-array-article.html

So I tried this code to see if I understood it correctly:

---
import std.stdio;

void main() {
  auto a = new int[5];
  auto b = a;

  a[0] = 1;

  for(auto i = 0; i < 100; i++) {
    a ~= 0;
  }

  a[0] = 2;

  writefln("a[0] = %d", a[0]);
  writefln("b[0] = %d", b[0]);
}
---

This prints:

a[0] = 2
b[0] = 1

That is, "a" was resized to a point where it needed to reallocate its contents. "b" still holds a reference to the old data. When, after the for loop, I change a's data, b's data doesn't change.

Is this expected behaviour?

How can I safely pass around a dynamic array without being afraid someone will keep an old copy of the data?
January 30, 2014
> This prints:
>
> a[0] = 2
> b[0] = 1
>
> That is, "a" was resized to a point where it needed to reallocate its contents. "b" still holds a reference to the old data. When, after the for loop, I change a's data, b's data doesn't change.
>
> Is this expected behaviour?

That's how it is.

> How can I safely pass around a dynamic array without being afraid someone will keep an old copy of the data?

I don't understand your exact requirements. Do you want to make sure that everyone sees the updates to the array, even after a relocation?
January 30, 2014
On Thursday, 30 January 2014 at 10:43:55 UTC, Ary Borenszweig wrote:
> Hi,
>
> I just read this nice article about slices: http://dlang.org/d-array-article.html
>
> So I tried this code to see if I understood it correctly:
>
> ---
> import std.stdio;
>
> void main() {
>   auto a = new int[5];
>   auto b = a;
>
>   a[0] = 1;
>
>   for(auto i = 0; i < 100; i++) {
>     a ~= 0;
>   }
>
>   a[0] = 2;
>
>   writefln("a[0] = %d", a[0]);
>   writefln("b[0] = %d", b[0]);
> }
> ---
>
> This prints:
>
> a[0] = 2
> b[0] = 1
>
> That is, "a" was resized to a point where it needed to reallocate its contents. "b" still holds a reference to the old data. When, after the for loop, I change a's data, b's data doesn't change.
>
> Is this expected behaviour?
>
> How can I safely pass around a dynamic array without being afraid someone will keep an old copy of the data?

pass the array by ref, or make a wrapper struct that holds a pointer to a slice, or a wrapper class that holds the slice.

Alternatively, make a wrapper struct that disallows the append operator and always use std.array.refAppender
January 30, 2014
On Thursday, 30 January 2014 at 12:50:34 UTC, John Colvin wrote:
> On Thursday, 30 January 2014 at 10:43:55 UTC, Ary Borenszweig wrote:
>> Hi,
>>
>> I just read this nice article about slices: http://dlang.org/d-array-article.html
>>
>> So I tried this code to see if I understood it correctly:
>>
>> ---
>> import std.stdio;
>>
>> void main() {
>>  auto a = new int[5];
>>  auto b = a;
>>
>>  a[0] = 1;
>>
>>  for(auto i = 0; i < 100; i++) {
>>    a ~= 0;
>>  }
>>
>>  a[0] = 2;
>>
>>  writefln("a[0] = %d", a[0]);
>>  writefln("b[0] = %d", b[0]);
>> }
>> ---
>>
>> This prints:
>>
>> a[0] = 2
>> b[0] = 1
>>
>> That is, "a" was resized to a point where it needed to reallocate its contents. "b" still holds a reference to the old data. When, after the for loop, I change a's data, b's data doesn't change.
>>
>> Is this expected behaviour?
>>
>> How can I safely pass around a dynamic array without being afraid someone will keep an old copy of the data?
>
> pass the array by ref, or make a wrapper struct that holds a pointer to a slice, or a wrapper class that holds the slice.
>
> Alternatively, make a wrapper struct that disallows the append operator and always use std.array.refAppender

woops, sorry that last one doesn't help.
January 30, 2014
On Thu, 30 Jan 2014 05:43:55 -0500, Ary Borenszweig <ary@esperanto.org.ar> wrote:

> Hi,
>
> I just read this nice article about slices: http://dlang.org/d-array-article.html
>
> So I tried this code to see if I understood it correctly:
>
> ---
> import std.stdio;
>
> void main() {
>    auto a = new int[5];
>    auto b = a;
>
>    a[0] = 1;
>
>    for(auto i = 0; i < 100; i++) {
>      a ~= 0;
>    }
>
>    a[0] = 2;
>
>    writefln("a[0] = %d", a[0]);
>    writefln("b[0] = %d", b[0]);
> }
> ---
>
> This prints:
>
> a[0] = 2
> b[0] = 1
>
> That is, "a" was resized to a point where it needed to reallocate its contents. "b" still holds a reference to the old data. When, after the for loop, I change a's data, b's data doesn't change.
>
> Is this expected behaviour?

Yes, it is intrinsic on how slices and arrays work.

> How can I safely pass around a dynamic array without being afraid someone will keep an old copy of the data?

You can't. Why is that important? The use case (or case that you are troubled by) would help to explain I think.

-Steve