Is swift inout a variable or pointer parameter?

I feel a little lost using the quick inout parameter in the following code:

var shouldContinue: Bool = true func doSomeWork1(shouldContinue: inout Bool) { while shouldContinue { // ERROR: the compiler wants: doSomeWork2(shouldContinue: &shouldContinue) doSomeWork2(shouldContinue: shouldContinue) } } func doSomeWork2(shouldContinue: inout Bool) { while shouldContinue { } } 

Why does the compiler want doSomeWork2(shouldContinue: &shouldContinue) instead of the compiler wants: doSomeWork2(shouldContinue: shouldContinue) ? is not shouldContinue already a pointer to doSomeWork1 () ???

+5
source share
2 answers

Being a pointer, this is only a side effect of the optimization process for inout parameters. They actually work differently using copy-to-copy behavior. Thus, inside the function, this parameter is treated as a regular variable, not a pointer. If you pass it to another function that takes an inout parameter, you should mark it as such.

Insert options are passed as follows:

When a function is called, the value of the argument is copied.

In the body of the function, the copy changes.

When the function returns, the value copys is assigned to the original argument.

This behavior is called copying or copying by result. For example, when a computed property or property with observers as an input parameter, its getter is called part of the function call and its setter is called as part of the function return.

As an optimization, when the argument is a value stored at a physical address in memory, the same memory location is used both inside and outside the function body. Optimized behavior is called the Help call; It satisfies all copying requirements while removing copying overhead. Write your code using the model provided by copying in copy, depending on the optimization on request, so that it behaves correctly with no optimization.

I / O Options

+7
source

From: Matt Neuburg Book 'Fundamentals of iOS 13 Programming with Swift.' :

If we want the function to change the original value of the argument passed to it, we must do the following:

  • The type of parameter that we are going to change must be declared inout .
  • When we call the function, the variable containing the mutable value must be declared with var, not let.
  • Instead of passing a variable as an argument, we should pass its address. This can be done by prepending an ampersand (& amp;) in front of its name.

Our removeCharacter (_: from :) method now looks like this:

  func removeCharacter(_ c:Character, from s: inout String) -> Int { var howMany = 0 while let ix = s.firstIndex(of:c) { s.remove(at:ix) howMany += 1 } return howMany } 

And our call to removeCharacter (_: from :) now looks like this: var s = "hi" let result = removeCharacter ("l", from: & s) After the call, the result is 2, and s is "heo". Note the ampersand before the name s when we pass it as an argument from::. Required; if you skip this, the compiler will stop you. I like this requirement because it forces us to explicitly admit to the compiler and ourselves that they were going to do something potentially dangerous: to allow this function, as a side effect, to change the value outside of itself.

0
source

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


All Articles