Why is it difficult to reference arrays in structs?

Mike Parker aldacron at gmail.com
Thu Oct 3 05:29:13 UTC 2019


On Thursday, 3 October 2019 at 04:32:52 UTC, Brett wrote:

>
> Ok, fine!
>
> auto r = &x.a;
>
> Now r is a reference, great!

No, r is a pointer, not a reference. D does not have reference 
variables.

>
> But now the semantics of using the array completely change and 
> errors abound!

Probably because you're trying to use r as if it were of type Y[] 
when it's really of type Y[]*, i.e. if you wanted to append to it 
you would need to first dereference the pointer:

*r ~= Y(10.0);

>
> Normal D pointers tend to act very nice, e.g., we don't have to 
> use the C++ -> BS....
>
> But with arrays it seems things are all screwed up and do not 
> work correctly.

No, they're working as intended.

>
> I can't just use r like I used x.a. I can't even use *r as 
> things then get even more screwed up.

Appending to *r works as expected:

https://run.dlang.io/is/IQa619

What sort of trouble did you encounter?

>
> I want to have a slice of an array that I can append to as a 
> sort of temporary and have it append to the main array(the end 
> of the slice always is the end of the main array)..

Your issue has nothing to do with structs.

As per the documentation:

https://dlang.org/spec/arrays.html#slicing

the initialization of b here creates a slice referencing a:

int[] a = [0, 1, 2];
int[] b = a;

As a slice, b has its own .ptr and .length properties that are 
distinct from those of a. They are initialized with the values of 
a's properties, but they *are not references* to a's properties 
and b is *not a reference* to a.

assert(b.ptr == a.ptr);
assert(b.length == a.length);

Because b.ptr and a.ptr point to the same memory, any updates to 
existing array elements through one will be reflected in the 
other:

a[1] = 3;
writeln(b); // prints [0, 3, 2]

But any changes to the .ptr or .length of one will not be 
reflected in the other:

a ~= 10;
assert(a.length == 4);
assert(b.length == 3);

writeln(a); // prints [0, 3, 2, 10];
writeln(b); // prints [0, 3, 2];

Though at this point, depending on whether or not a reallocation 
took place, they might still be pointing to the same block of 
memory.

> I've tried assumeSafeAppend but it does nothing to help.

assumeSafeAppend is for telling the runtime that you want to 
reuse an existing memory block backing an array and there's no 
need to reallocate it in append.

https://dlang.org/articles/d-array-article.html#slice-members-appender

> The reason is because i have an algorithm that generates data 
> and stores it in an array > and it is more efficient and easier 
> to code if I can just append data to a "slice" of the 
> array(there are no issues with overwriting).
>
> Essentially it just acts as an alias.
>
> By using pointers it would work but it screws up the entire 
> syntax of all the code and > then still doesn't work.

Could you adjust the signature of your algorithm to take the 
array by ref?

void myAlgo(ref Y[] arr) {
     arr ~= Y(10.2);
}

Or to take x by ref (or as a pointer) and manipulate the array 
directly:

void myAlgo(ref X x) {
     x.a ~= Y(10.2);
}



More information about the Digitalmars-d-learn mailing list