Does inout/var parameter make any difference with reference type?
Asked Answered
T

2

8

I know what inout does for value types.

With objects or any other reference type, is there a purpose for that keyword in that case, instead of using var?

Code example:

private class MyClass {
    private var testInt = 1
}

private func testParameterObject(var testClass: MyClass) {
    testClass.testInt++
}

private var testClass: MyClass = MyClass()
testParameterObject(testClass)
testClass.testInt // output ~> 2

private func testInoutParameterObject(inout testClass: MyClass) {
    testClass.testInt++
}

testClass.testInt = 1
testInoutParameterObject(&testClass) // what happens here?
testClass.testInt // output ~> 2

It could be the same as simply the var keyword in the parameter list.

Theatrical answered 1/2, 2015 at 14:30 Comment(0)
O
11

The difference is that when you pass a by-reference parameter as a var, you are free to change everything that can be changed inside the passed object, but you have no way of changing the object for an entirely different one.

Here is a code example illustrating this:

class MyClass {
    private var testInt : Int
    init(x : Int) {
        testInt = x
    }
}

func testInoutParameterObject(inout testClass: MyClass) {
    testClass = MyClass(x:123)
}

var testClass = MyClass(x:321)
println(testClass.testInt)
testInoutParameterObject(&testClass)
println(testClass.testInt)

Here, the code inside testInoutParameterObject sets an entirely new MyClass object into the testClass variable that is passed to it. In Objective-C terms this loosely corresponds to passing a pointer to a pointer (two asterisks) vs. passing a pointer (one asterisk).

Outward answered 1/2, 2015 at 14:39 Comment(4)
Thanks, it is a bit tricky, since there is no warning that setting the var parameter to a new object does simply nothing. I just oversaw that. It is the same for all reference types then?Theatrical
@ViktorLexington Yes, this is the same for reference types. Strictly speaking, setting a plain var does something - it changes the object for the duration of the function, in the same way that a pass-by-value in Objective-C would let you change parameters without making changes in the caller's context.Outward
@dasblinkenlight tiny follow up question, in addition to the above (where inout lets you literally replace the object instance referred to by the parameter), am I correct in my assumption that if I pass a reference type (object) in swift as a standard parameter type (no inout and no var), that IF a property of the object is modified by a function it was passed to, then that change will exist outside the scope of the function? i.e. changes to ref types inside functions are seen outside functions (even without var/inout). correct?Unkenned
@Unkenned Yes. If you modify the properties of a passed-in object inside a function, those changes will be visible outside the function's scope. This is a very common pattern; the inout keyword should only be used when the function modifies the variable itself (i.e., replaces the object it refers to with another one).Fribble
E
4

It does the exact same thing for all types. Without inout, it is pass-by-value (regardless of type). That means assigning (=) to the parameter inside the function has no effect on the calling scope. With inout, it is pass-by-reference (regardless of type). That means assigning (=) to the parameter inside the function has the same effect as assigning to the passed variable in the calling scope.

Extraditable answered 1/2, 2015 at 19:6 Comment(10)
@ViktorLexington: Isn't that exactly what I said? Please be specific about whether you agree with my answer or not, and if not, which part you do not agree with.Extraditable
The question was, if there is a difference with both of the keywords, var and inout FOR REFERENCE TYPES are pass by reference. It is always pass by reference. Passing a reference as value is also pass by reference.Theatrical
The accepted answer showed me the difference between pass by reference and pass by double reference like often used by nserror in objective cTheatrical
@ViktorLexington: "Passing a reference as value is also pass by reference." ABSOLUTELY NOT. That is Pass-by-Value. Without inout is always pass-by-value. With inout is always pass-by-reference. This is true regardless of value type or reference type.Extraditable
an object is a refetence type, pass it without inout, and you are passing the object (like inout with value types), which is effectivly pass by reference, try it out. Changing the value of that object also changes the orginal object (without inout)! Did you even read my question with the code?Theatrical
@ViktorLexington: You cannot "pass an object" because objects are not values in Swift. You can have references to objects which are values. If we don't have inout and &, passing and assigning in Swift is semantically identical to that in Java (which also has value types and reference types). Look anywhere on StackOverflow or the Internet and Java is always described as pass-by-value only.Extraditable
@ViktorLexington: The question is "Does inout parameter make any difference with reference type?" The answer is, there is a difference and it is the exact same difference as with value types, which is: pass-by-value vs. pass-by-reference. There is no difference between types. How is that not a right answer to the question?Extraditable
The question states clearly it is only about reference types. Even if it does technically behave the same like value types, it is semantically different, a var parameter with a reference type does copy the address but it is pass by reference. The question was, what can I do with inout reference type parameter more - answer is: set the reference to another object.Theatrical
@ViktorLexington: "it is semantically different" It is semantically identical. "but it is pass by reference" Again, it is PASS-BY-VALUE. It is semantically identical to Java, which is pass-by-value only.Extraditable
I am sorry. I looked up different websites before and all defined pass by reference wrong! What I meant was: When I already have a pointer to something and I am copying the pointer, the parameter isn't the value, it is the pointer. I did understand that you meant passing the value of the address of the object, but thought pass by reference only means having a pointer to an object. I should research better next time. (Apple should have called it pointer type, reference type is misleading that reference is for parameters)Theatrical

© 2022 - 2024 — McMap. All rights reserved.