Its basically like (probably IS under the hood) Pointers.
so for some arrays a and ba = b
thats basically copying the pointers themselves. So whatever changes i
make in A will be reflected in B.
Roughly. The Array itself exists on the heap independently of a and b; a and
b are local variables, basically just slots in the stack which contain a
reference to the Array.
The difference is that local variables themselves are not objects, and you
cannot take a "reference" to a or b.
So whereas in C you could write
void *p = malloc(50);
void *q = p; # q is a another pointer to the malloc space
void **r = &p; # r points to the pointer p <<<< NOTE
in Ruby you can only do
p = "x" * 50
q = p
This actually makes life simpler. If you call
foo(p)
then the method foo can mutate the object p, but on return p will definitely
be unchanged, i.e. is a reference to the same object. You cannot change what
p references, unless you explicitly return a new object, e.g.
p = foo(p)
Of course, the biggest simplification over C is garbage collection. The
Array will be garbage collected once nothing else contains a reference to it
(either a local variable or another live object)
a = b.dup
create some NEW pointers but which point to the same memory space.
No. It allocates new memory space and copies the contents of the space
referenced by 'a' into the new space.
However, that space may in turn contain pointers (references) to other
memory spaces (objects). Since this is a direct copy, the new object
contains the same references as the old object.
obj1 = "foo"
obj2 = "bar"
a = [obj1, obj2] # a points to an Array which contains &obj1,&obj2
b = a.dup # b points to a different Array which contains
# &obj1, &obj2
In the latter case you could have written b = [a[0], a[1]], or
b = [obj1, obj2], and got the same result: a new array, which contains the
same pointers as the old array.
You can modify the array referenced by b - e.g. by adding or replacing an
element - and this won't affect the other array referenced by a. But if you
follow b[0] to find obj1, and modify obj1, then obj1 is changed.
Subsequently accessing the object referred to by a[0] or b[0] will find the
same changed obj1.
Use the "object_id" method to see if you're pointing to the same "memory
space".
irb(main):001:0> a = ["abc","def"]
=> ["abc", "def"]
irb(main):002:0> a.object_id
=> -605609816
irb(main):003:0> b = a.dup
=> ["abc", "def"]
irb(main):004:0> b.object_id
=> -605638770
You can think of object_id as a kind of encoded pointer.
HTH,
Brian.