I encountered some strange inconsistent behavior with ref types while toying around with some Nim code. The very helpful folks in discord server suggest asking here since they don’t really have the explanation.
type ob = ref object
proc ret(): ob =
var a = ob()
# proc inner(): ob = a
echo cast[int](a.addr) # this is different
return a
let c = ret()
let b = ret()
let d = ret()
echo cast[int](b.addr) # from this
echo cast[int](c.addr) # from this
echo cast[int](d.addr) # from this
140723443280672
140723443280672
140723443280672
94867386982632
94867386982624
94867386982640
As I return the ‘ref’ instance, I got a copy of its content, but that copy of stays consistent for some reason.As I read this here again: I correct myself, the copy does not stay consistent. it's just allocated continuously in this case, so the last 2 digits are not the same.
So the initial instance in the proc stays consistent as that's always the same, but you get a different copy out of that proc every time.
One thing to note is that you are echoing the address of the variable, not the actual address you are pointing to (this is why the address in the proc stays the same)
If you just do cast[int](yourVar) then you'll see the addresses line up
I'm personally curious now so I tried this out. They do not line up in my attempt:
type ob = ref object
name: string
proc ret(): ob =
let a = ob(name: "yalalalalalalal")
# proc inner(): ob = a
echo cast[int](a) # this is different
return a
let c = ret()
let b = ret()
let d = ret()
echo cast[int](b) # from this
echo cast[int](c) # from this
echo cast[int](d) # from this
140131146870880 # ret-call for c
140131146870912 # ret-call for b
140131146870944 #ret-call for d
140131146870912 #echo of b
140131146870880 # echo of c
140131146870944 # echo of d
# Re ordered so that invocation and echo are next to one another
140131146870880 # ret-call for c
140131146870880 # echo of c
140131146870912 # ret-call for b
140131146870912 #echo of b
140131146870944 #ret-call for d
140131146870944 # echo of d
In this scenario we're witnessing the creation of 3 independent instances of ob (one for each ret-call) and it gets assigned to a variable. The instance inside the proc and outside the proc stays consistent.most likely, there is a need to understand what ref object is. here is an example what happend if it was c
void* ret() {
void* a = malloc(1); // sizeof empty object
printf("%p\n", &a); // printing addr of a
return a; // returning pointer to some object
}
int main() {
void *c = ret();
printf("%p\n", &c); // printing addr of c
return 0;
}
as you can see you printing address of variable storing pointer not address of object
let's change your nim code to print object ref
type ob = ref object
proc ret(): ob =
var a = ob()
echo cast[int](a)
return a
let c = ret()
echo cast[int](c)