I believe that this is what happens. When you appoint
a = []
you point a to a new array. The original array still exists in memory and when you do:
b = 99
you are modifying the original array, not the new array that refers to a .
What evidence do you have that this is so?
Consider this modification for your experiment:
Case 1:
func foo(inout a: [Int], inout b: Int) { a[0] = 4 a[1] = 5 a[2] = 6 b = 99 } var arr = [1,2,3] foo(&arr, b: &arr[2]) print(arr)
Now consider this:
Case 2:
func foo(inout a: [Int], inout b: Int) { a = [4, 5, 6] b = 99 } var arr = [1,2,3] foo(&arr, b: &arr[2]) print(arr)
It is clear that changing the individual elements of a does not coincide with the purpose of the array a .
In case 1, we modified the initial array, turning the elements into 4 , 5 and 6 , and the purpose of b changed a[2] , as expected.
In case 2, we assigned [4, 5, 6] to a , which did not change the original values โโto 4 , 5 and 6 , but instead pointed a to a new array. Assigning b does not change a[2] in this case, because a now points to a new array elsewhere in memory.
Case 3:
func foo(inout a: [Int], inout b: Int) { let a1 = a a = [4, 5, 6] b = 99 print(a) // prints "[4, 5, 6]" print(a1) // prints "[1, 2, 99]" } var arr = [1,2,3] foo(&arr, b: &arr[2]) print(arr) // prints "[4, 5, 6]"
In case 3, we can assign the original array a1 before assigning a new array a . This gives us a name for the original array. When b is assigned, a1[2] changes a1[2] .
From the comments:
Your answer explains why the assignment of function b inside the function works. However, when foo finishes and copies the inout variables back, at this point I do not see how quickly it is known to defer the release of the original array to the destination & [2].
This is probably the result of ARC reference counting. The original array is passed by reference foo , and the reference counter is incremented. The original array is not freed until the reference count decreases at the end of foo .
It seems as hairy as the fact that the documents have already banned - the passage is the same variable twice as much as inout. Also your case3 is amazing. shouldn't let a1 = a line do struct / value semantics and copy the snapshot array to the right ??
Yes. I agree that case 3 is surprising, but it shows some of what is happening under the covers. Usually, when you assign one array to a new variable, Swift does not instantly create a copy. Instead, it simply points the second array to the first, and the reference count is incremented. This is done for efficiency. It is only necessary to make a copy when one of the arrays is modified. In this case, when a changes, a1 stores the original copy of the array in memory.
This is really confusing; I do not understand why a1 will not get 1,2,3. Also let it be unchanged!
The fact that a1 changes when b set indicates that a1 points to the memory of the original array. Obviously, Swift does not view installation b as a modification of a1 . Perhaps because he was already convinced that a was changed when calling foo with &a[2] .