Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using inout keyword: is the parameter passed-by-reference or by copy-in copy-out (/call by value result)

Tags:

swift2

inout

Question: Based on the information and discussion below: Are inout parameters passed-by-reference or by copy-in copy-out?


Based on the following SO threads, function parameters marked by the inout keyword is passed by reference:

  • Does inout/var parameter make any difference with reference type?
  • Is Swift Pass By Value or Pass By Reference
  • Why doesn't inout pass by reference?

We note that the two top-most threads are pre-Swift 2.0; I haven't been able to find any newer discussion on the subject here on SO (except the somewhat related third thread link).


Based on Apple's documentation (as far as I've been able to discern), however, function parameters marked by the inout keyword is passed by copy-in copy-out (or call by value result)

  • Apple Language Reference: Declarations - In-Out Parameters:

In-out parameters are passed as follows:

When the function is called, the value of the argument is copied. In the body of the function, the copy is modified. When the function returns, the copy’s value is assigned to the original argument. This behavior is known as copy-in copy-out or call by value result. ...

  • Apple Language Guide: Functions - In-Out Parameters:

... You write an in-out parameter by placing the inout keyword at the start of its parameter definition. An in-out parameter has a value that is passed in to the function, is modified by the function, and is passed back out of the function to replace the original value. ...


Now for my own example trying to investigate this:

struct MyStruct {
    private var myInt: Int

    mutating func increaseMyInt() {
        myInt++
    }

    func printMyInt() {
        print(String(myInt))
    }

    init(int: Int) {
        myInt = int
    }
}

class MyClass {
    var myStruct: MyStruct

    init(int: Int) {
        myStruct = MyStruct(int: 1)
    }

    func printMyStructsInt() {
        print(String(myStruct.printMyInt()))
    }
}

func myInOutFunc(inout myLocalStruct: MyStruct, myClass: MyClass) -> Int {
    myClass.printMyStructsInt() // prints "1", OK
    myLocalStruct.increaseMyInt()
    myClass.printMyStructsInt() // prints "2": so myStruct is not a copy here?
    myLocalStruct.increaseMyInt()

    return 0
        // according to Apple's doc, shouldn't myStruct member of myClass get
        // assigned (copy of) value of myLocalStruct at this point, and not
        // prior to this?
}

var a = MyClass(int: 1)

a.printMyStructsInt() // prints "1", OK
myInOutFunc(&a.myStruct, myClass: a)
a.printMyStructsInt() // prints "3", OK

This example would imply that inout parameters are indeed passed by reference (as is noted in the two linked SO threads above). Since we prefix the inout parameter with an ampersand (&) this does "feel" logical.

To try my best to make sure that my example is representative---since here inout parameter myLocalStruct is sent as class property---I also made sure that the myLocalStruct didn't get some "behind-the-hood" reference due to it being a class property:

// ... add to bottom of the code above

func testSendStructAsPublicClassProperty(var myLocalStruct: MyStruct) {
    myLocalStruct.increaseMyInt()
}

// test that sending class property doesn't "reference" things up
a.printMyStructsInt() // prints "3"
testSendStructAsPublicClassProperty(a.myStruct)
a.printMyStructsInt() // prints "3", OK (only copy of class property is sent)

Ok, myLocalStruct in this example really function-local, and hence passed by value (no reference-behind-the-hood).


Result: Given the above, inout parameters are passed by reference?

I have two possible follow-up questions:

  1. Have I misinterpreted the description on inout in the Apple language doc, can it be interpreted as "pass by reference"?
  2. Or, is my example still not representative for this case?
like image 841
dfrib Avatar asked Dec 21 '15 16:12

dfrib


People also ask

What is an inout parameter?

An inout parameter is a special type of parameter that can be modified inside a function and the changes apply outside the function.

What is in out inout parameters?

Procedure with IN-OUT parameter: An INOUT parameter is a combination of IN and OUT parameters. It means that the calling program may pass the argument, and the stored procedure can modify the INOUT parameter and pass the new value back to the calling program.

What does Inout mean Swift?

All parameters passed into a Swift function are constants, so you can't change them. If you want, you can pass in one or more parameters as inout , which means they can be changed inside your function, and those changes reflect in the original value outside the function.

What is a good use case for an inout parameter Swift?

A good use case will be swap function that it will modify the passed-in parameters. Swift 3+ Note: Starting in Swift 3, the inout keyword must come after the colon and before the type. For example, Swift 3+ now requires func changeChar(char: inout Character) .


1 Answers

The next two paragraphs in the Language Reference describes it more in detail:

In-Out Parameters

This behavior is known as copy-in copy-out or call by value result. For example, when a computed property or a property with observers is passed as an in-out parameter, its getter is called as 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. The optimized behavior is known as call by reference; it satisfies all of the requirements of the copy-in copy-out model while removing the overhead of copying. Do not depend on the behavioral differences between copy-in copy-out and call by reference.

So it's de facto "pass by reference"

like image 106
vadian Avatar answered Jan 04 '23 14:01

vadian