On Saturday, 14 November 2015 at 10:46:57 UTC, Alex wrote:
Hi everybody,
I have the following question about "by reference" behavior
related to structs.
I have a struct, say S, which contains a member of reference
type
struct S
{
int[] member;
}
and I have a main, for testing:
void main()
{
S s; // = new S();
s.arr = [1,2,3];
writeln(s.arr); //first
S t; // = new S();
t = s;
writeln(t.arr); //second
s.arr ~= 4;
writeln(s.arr); //third
writeln(t.arr);
}
So, I create a first var of type S, then the second and copied
the first into the second. The behavior is like intended, the
array inside the struct is copied. But this is a deep copy, as
the third block shows. If I change the array in the 's' var, it
is not propagated into the 't' var.
Actually, no, it isn't a deep copy. You seem to be missing the
fundamentals of how slices (dynamic arrays) work in D. Read
Steven's article at [1] for the details. Essentially, you can
think of an array in D like this:
struct Array(T) {
size_t length;
T* ptr;
}
When you assign s to t, this is what is being copied... *not* the
contents of the array. Both arrays will still point into the same
memory. Add these two lines immediately after t = s:
writeln(s.arr.ptr);
writeln(t.arr.ptr);
You will see they print the same address. If you try something
like this:
s.arr[0] = 100;
You will see the change reflected in both s and t. Add the same
two calls to writeln after s ~= 4 and you will see the addresses
are now different. Steven's article explains what's going on.
What I want to do is: the propagation of changes to all vars,
which are copies of the first one.
The idea which works:
change the definition of S into class and add 'new' on defining
the vars.
Then, the example shows the desired behavior.
For what you want to do, this is probably your best option. The
other is work with S by pointer, but then you can still use S as
a value type. Structs are value types, classes are reference
types. If you never want the behavior of a value type for a given
type, use a class.
The second idea: implement a postblit into the struct S.
The problem hereby is, how to reference the unique var more
then once? How does the postblit looks like? Is it simple a
@disable this(this)? But then, I couldn't copy the vars at
all... but indeed I don't want to copy them, I rather would
like to reference them, if they are intended to mirror the same
internal value. Is this idea possible at all?
postblit is often used to make sure you get a deep copy of an
array or any reference types:
struct S
{
int[] arr;
this(this) {
arr = arr.dup;
}
}
[1] http://dlang.org/d-array-article.html