on structs by reference
Mike Parker via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Sat Nov 14 03:48:41 PST 2015
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
More information about the Digitalmars-d-learn
mailing list