Search code examples
swiftreferenceinout

Inout in swift and reference type


I'm trying to understand the difference between value and reference type. And now I want to use function from the apple guide:

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
  let temporaryA = a
  a = b
  b = temporaryA
}

and if I want to use this is function I will write this code

swapTwoInts{&firstIntStruct, &secondIntStruct}

I understand that we must put in this function reference type, but Int is a value type, therefore we use &.
In another hand, when I try change Int to my class in the swap function, I also must write & before instance of my class.

Why I must do it, if it is the reference already?


Solution

  • Suppose we wrote the hypothetical function you're talking about:

    class C {}
    
    func swapTwoC(_ lhs: C, rhs: C) {
        let originalLHS = lhs
        lhs = rhs
        rhs = originalLHS
    }
    

    The immediate problem is that lhs and rhs are immutable. To mutate them, we would need to make mutable copies:

    func swapTwoC(_ lhs: C, rhs: C) {
        var lhs = lhs; var rhs = rhs
        let originalLHS = lhs
        lhs = rhs
        rhs = originalLHS
    }
    

    But now the problem is that we're mutating our copies, and not the original references our caller gave us.

    More fundamentally, the issue is that when you pass a reference (to an instance of a class, which we call an object) to a function, the reference itself is copied (it behaves like a value type). If that function changes the value of the reference, it's only mutating it own local copy, as we saw.

    When you have an inout C, and you pass in &myObject, what you're actually passing in is a reference to your reference to myObject. When the function arguments are copied, what's copied is this "ref to a ref". The function can then use that "ref to a ref" to assign a new value to the reference myObject the caller has