Stupid question about AA. The following code works but I don't undrstand why?!

ag0aep6g via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Apr 9 14:13:32 PDT 2016


On Saturday, 9 April 2016 at 19:25:32 UTC, Uranuz wrote:
> Another observation is illustrated with the foloving code:
> http://dpaste.dzfl.pl/8d68fd5922b7
>
> Because AA and arrays are not created before they were assigned 
> some value it leads to inconsistency in behavior. And will 
> produce unexpected and hidden bugs that is not good. It's not 
> very good side of D's array and AA. But classes could be also 
> affected by this *feature* (or bug, as you wish). So we must 
> always construct reference semantics types before passing them 
> to functions that will modify it. For classes it's obvious but 
> for AA and dynamic arrays is not.

The inconsistency is only there with associative arrays, where 
adding a key may or may not affect other views of the AA, 
depending on if the AA was empty before or not.

In code:
----
int[int] aa1;
...
int[int] aa2 = aa1;
aa2[0] = 0; /* may or may not affect aa1 */
----

With dynamic arrays, appending does never affect other views, no 
matter if the array was empty or not.

In code:
----
int[] a1;
...
int[] a2 = a1;
a2 ~= 1; /* never affects a1 */
----

Dynamic arrays do have a similar oddity, but it doesn't depend on 
empty/non-empty. It depends on the capacity. When you append to a 
dynamic array that has no capacity left, a new copy of the data 
is made. The dynamic array then becomes independent of other ones 
with which it used to share data.

In code:
----
int[] a1 = [0];
...
int[] a2 = a1;
a2 ~= 1; /* never affects a1 */
a2[0] = 1; /* may or may not affect a1 */
----

With class references I can't see any inconsistency. When you're 
given a null reference, all you can do is construct an object 
there, which never affects other copies of the reference. And 
when you mutate through a non-null reference, that always affects 
other copies of the references, of course.

In code:
----
class C {int x = 0;}
C c1;
...
C c2 = c1;
c2 = new C; /* never affects c1 */
c1 = c2;
c2.x = 1; /* obviously affects c1 */
----

> Another solution is to pass reference types by *ref*. So you 
> will not have such bugs in implementation

Yup, if you mean to affect the passed variable, ref is the way to 
go. And if you don't mean to affect the passed variable, you 
should probably mark the parameters const, or at least the 
reference part of the parameters (e.g. const(int)[]).


More information about the Digitalmars-d-learn mailing list