Thread overview | |||||
---|---|---|---|---|---|
|
February 11, 2016 Odd Associative Array Reference Behavior | ||||
---|---|---|---|---|
| ||||
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? |
February 10, 2016 Re: Odd Associative Array Reference Behavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matt Elkins | 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
|
February 11, 2016 Re: Odd Associative Array Reference Behavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Thursday, 11 February 2016 at 03:47:09 UTC, Steven Schveighoffer wrote:
> 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.
Makes sense (though it defies my intuition; I would have expected an NPE or crash at time of assignment). Thanks!
|
Copyright © 1999-2021 by the D Language Foundation