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

Reply via email to