I have this situation (code to demonstrate my confusion)

var my_pool:PoolVector3Array
 
 func calling_func():
	my_pool[0] = Vector3.ZERO
	modifying_func(my_pool)
    print("my-pool", to_json(my_pool)  // prints ZERO not UP!

 func modifying_func(p: PoolVector3Array): p[0] = Vector3.UP

So it occurs to me that maybe the engine is cloning on modification? If so, this is not the kind of thing I expected. If I pass by reference I want passed by reference...

@DaveTheCoder @dotted -- It's more complicated than that, which I think is important for efficient usage. There's a web of inter-linked engine issues around how to better-document or -implement this behavior: e.g. #15265.

My gist from reading the underlying pool_vector.cpp code is that the pool arrays are pass-by-value wrappers around a reference to the actual backing vector. These wrappers then implement copy-on-write behavior by only ever directly mutating the original backing vector when there is only a single reference to that vector, and otherwise point themselves to a copy which they then mutate.

This means you can treat the pool arrays as immutable, and passing them around for read-only access has no more overhead than passing by reference. But of course the downside is that the behavior is very confusing if one doesn't anticipate it!

I think the reasoning is sound, but there is a slight danger that comes with OO and thinking (naively) that the pool arrays are a subclass of array (they aren't).

In the end, it makes sense but for a 'normal' programmer who may not dig into or have the background to expect this, I can see it as a wrench in the works

Maybe the word "Array" in the type name should be removed. For example, rename the type to "Vector3Pool".

PackedVector3Array? That still contains "Array", so people might expect it to behave like a normal array.

That's true. I had only remembered they were renaming them. I like your name better

2 years later