Trying to understand pointers and aliasing

Hi there, I’m trying to understand what the difference is when you copy elements of an array to another array, vs. setting one equal to another (which results in both just being pointers to the same piece of memory, if I’m not mistaken?).

For example,

B = [1,2,3,4,5];
A = [10,11,12,13,14];
for i in 1:5
    B[i] = A[i]
end;
A[4] = 666;
B

gives the output

5-element Vector{Int64}:
 10
 11
 12
 13
 14

This makes sense to me, as I believe the loop is taking each element i of the vector A and copying it to B. Hence, when A is altered, B remains the same since it has copies of the old A entries instead of just pointers to the memory in A. Am I right in thinking this?

If so, then I can’t figure out what’s wrong with this code I’m working on, which has the following snippet:

for i in 1:length(phi)
    phi_matrix[n_step][i] = phi[i]
end

where phi_matrix is just a vector of vectors, each of the individual vectors being copies of phi at different timesteps n_step. Now, the code does what it’s meant to do when I write phi_matrix[n_step] = copy(phi) instead of the loop. This makes sense, but I’m allocating more memory to creating a copy of phi, it seems. However, if I use the loop above, every element of the phi_matrix seems to just be a pointer to whatever phi is, since at the end of the simulation every vector in phi_matrix appears to be a copy of the current phi. So why does the snippet above exhibit this aliasing effect that I would have thought doesn’t happen in loops, given the example I gave at the beginning of this question? If nobody thinks this should happen, then I’ll have a look at the rest of my code and see if something else is causing this problem.

Thank you!

Yes

This is because in your first example the elements of the vectors are immutable, thus sharing occurs by copying the values. In the second case your elements are mutable, and sharing occurs by copying the reference. When you do:

julia> x = [ [1,2] ]
1-element Vector{Vector{Int64}}:
 [1, 2]

julia> y = [ [3, 4] ]
1-element Vector{Vector{Int64}}:
 [3, 4]

julia> y[1] = x[1]
2-element Vector{Int64}:
 1
 2

julia> y[1] === x[1]
true

What is copied from x[1] to y[1] is the reference to the vector in x[1], not the vector itself.

4 Likes

Ohhhhh, I see. So scalar elements within a vector are immutable, but vectors themselves are mutable?

Also, the element phi[i] that I’m trying to assign to the phi_matrix[n_step] vector is itself just an element, rather than a vector. I’m not trying to assign a vector to another, right? So why does your argument apply?

1 Like

Yes

Than it should work exactly as in your first example. If it is not, the problem is somewhere else (and the argument doest not apply).

1 Like

See also the assignment vs. mutation section of the manual.

1 Like

Thank you both. I’ll have a look…