Odd Associative Array Reference Behavior

Steven Schveighoffer via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Feb 10 19:47:09 PST 2016


On 2/10/16 10:10 PM, Matt Elkins wrote:
> Consider the following definition of Foo and an accompanying unittest:
>
> [code]
> struct Foo
> {
>      @property int[int] aa() {return m_aa;}
>      @property ref int[int] aaRef() {return m_aa;}
>      int[int] m_aa;
> }
>
> unittest
> {
>      Foo foo;
>      assert(5 !in foo.m_aa); // Sanity-check to start off
>      foo.aa[5] = 1;          // Add an element with key 5
>      assert(5 !in foo.m_aa); // ...huh. 5 didn't make it in?
>      foo.aaRef[5] = 1;       // Try again, using the ref variant
>      assert(5 in foo.m_aa);  // Works!
> }
> [/code]
>
> I was under the impression that associative arrays are reference types;
> if I pass a non-ref "copy" of one, shouldn't insertions still be
> reflected in the original? Am I dealing with a bug or a misunderstanding
> on my part?

Misunderstanding.

An AA under the hood is simply a pointer. Initialized to null.

When you pass it around, you are passing a pointer. AA assign checks for 
null and allocates a new AA impl to hold the data. But this doesn't 
affect other copies (that were null).

So what is happening is aa() returns a null AA. You assign to it, which 
allocates a new AA impl, and sets the rvalue to point at it. The rvalue 
promptly disappears. The original m_aa is still set to point at null.

If you add more elements, you will see you can do so using the non-ref 
version. It's only on the first assignment that the reference changes. 
After that, it's the same reference forever (unless reassigned of course).

-Steve


More information about the Digitalmars-d-learn mailing list