on structs by reference
Alex via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Sat Nov 14 07:53:11 PST 2015
On Saturday, 14 November 2015 at 11:48:42 UTC, Mike Parker wrote:
>> 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:
Yeah... you could be right... Just finished the awesome lecture,
thank you for the link. So, let us speak in terms of content and
topology, where by topology for the most part is meant the length
of the array.
> 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.
Yes. I tried this out. The difference seems clear now: If I try
to alter the content at some place, where some slices point to,
then all this slices will mirror the change. And if I alter* the
slice itself, it is not said, that it will point to the same
array. All right.
*And by alter, I mean: changing the topology in a way that is
incompatible with the previous underlying array.
> 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.
Yeah... this belongs to the conceptual part of my question. The
difference between structs as value types and classes as
reference types is more or less clear. The question is, how to
define when a behavior is not a value type behavior any more.
> 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;
> }
> }
>
Ok, so this is far away from what I want.
So now the question which I still have: I want to reduce my slice
inside my struct 's' step by step. So, the only operations I want
to make should not lead to a reallocation of the underlying
buffer.
But I want to control at which side (from the front, or from the
back) of the slice the reducing step should be made and, if there
are some other copies (or references) to the slice of the same
size (same size and same beginning point, indeed) they should be
reduced also.
Some comments to myself:
1. Concerning ***: if the pointer and length are passed by value
for each slice reference, then the simultaneous change is not
possible, as the 'topology' is passed by value.
2. Indeed, the simultaneity itself speaks in favor of using a
'class S' instead of a 'struct S'.
3. The only point I stumble on is, that the main feature in my
program is, that the underlying array, to which my slices refer
to never changes. So, I'm going to have more and more slices,
which are going to be smaller and smaller and each points to the
same underlying array without overlapping, but at each step,
there are as much copies of a single slice as elements it points
to. I hope this last point was not too weird.
More information about the Digitalmars-d-learn
mailing list