On 1/22/20 10:33 AM, Adam D. Ruppe wrote:
BUT if you change the length of it or reallocate it in any way those
changes are NOT seen outside.
So with AAs and slices, if you just want to work with existing elements,
no need for ref. But if you are going to do any kind of resizing -
adding or removing elements - ref is likely what you want.
So just to clarify this a bit for AAs. Adding or removing elements from
an AA DOES get seen outside, even if you don't pass by ref, except for
one case -- the AA is in its initial state.
The reason is because an AA is actually a pointer-to-implementation
(pImpl) struct, which is initialized to null, but allocated on first
element added.
So if you don't add any elements, and pass it by value, you are passing
null by value, and adding elements will allocate it. But the result
doesn't get seen back at the parameter you passed.
However, if you add one element, and then pass it, the implementation is
already allocated and does not change locations. So then you can add
more elements even if you pass by value, and the implementation stays at
the same location.
example:
void foo(int[int] p)
{
p[1] = 1; p[2] = 2;
}
int[int] aa;
foo(aa);
assert(aa.length == 0); // new allocation in foo not seen
aa[0] = 0; // first initialization, no longer null
foo(aa);
assert(aa.length == 3); // now, you see the changes
aa.clear(); // remove all elements, but don't deallocate.
assert(aa.length == 0);
foo(aa);
assert(aa.length == 2); // was already preallocated, so impl stays the same.
This aspect is very confusing to many people.
-Steve