From: Brian Candler Date: 2008-08-28T16:35:20+09:00 Subject: Re: how to avoid passing by reference and how to copy objects > Its basically like (probably IS under the hood) Pointers. > so for some arrays a and b > > a = 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.