trying to understand in, inout, and ref...

Steven Schveighoffer schveiguy at gmail.com
Wed Jan 22 16:51:56 UTC 2020


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


More information about the Digitalmars-d-learn mailing list