Not sure how safe this inactivity scenario is, since the array becomes invalid when returning

The code below does not crash, but I canโ€™t explain why, given the available โ€œavailableโ€ documents.

func foo(inout a: [Int], inout b: Int) { a = [] b = 99 } var arr = [1,2,3] // confusion: where does the "out" of b go to? // storage for a was already cleared / invalidated foo(&arr, b: &arr[2]) print(arr) // arr is empty 
+5
source share
1 answer

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) // prints "[4, 5, 99]" 

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) // prints "[4, 5, 6]" 

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] .

+2
source

Source: https://habr.com/ru/post/1235919/


All Articles