Well, not for Julia Vectors. You can push!
and pop!
elements onto or off from the end of Vectors (length changes, capacity always increases), for instance, and when it starts running out of the allocated space, the memory buffer is reallocated to a different bigger spot (pointer changes). But that’s not actually the general reason that mutable objects aren’t stored inline, just an Array implementation detail. For example, you can make a mutable type with a fixed size: mutable struct MutInt num::Int end
, which won’t be stored inline either.
Again, the reason is mutability. Bear in mind that Julia’s concept of mutability isn’t shared by all languages because Julia treats variables and other references like names to be attached to objects (like Python does). So you can attach two references to the same instance: x = MutInt(3); A[1] = x
. Mutability doesn’t only mean the instance can change; if you think about it, you don’t actually need that all too often, you can just reassign variables to different instances e.g. count += 1
. It also means that all the references access the change, so x.num = 5
changes x
and A[1]
. To pull that off, the actual num
field cannot be stored directly in x
or A
, but in a neutral 3rd-party location on the heap or stack. By definition, MutInt(3)
is not stored inline in A
because some of its data is not in A’s array buffer.
That’s essentially what happens. Very much like instances of MyStruct
outside of arrays, the fixed-size chunk in the array’s buffer contains a Float64
for the a
field and a pointer for the b
field. That’s not considered inline. I’m not actually sure where vector metadata is stored, Base.summarysize
doesn’t even count that bit of memory.