Inout
So far, we have only discussed pointers in terms of reference types. For the most part, this will work well, but sometimes you want something more flexible. This is where inout
s come in.
Note that there are some pointer types like UnsafeMutablePointer
UnsafeRawPointer
, etc., but these are very advanced and not what we will be discussing. The only time I have seen them used is when I was playing around with graphics.
Background
For those unfamiliar with the idea of pointers:
When we think about our variables, we think about the values they hold. For example, if we say var x = 3
we think x
being an Int
of value 3
. But, behind the scenes, x
is actually a location in memory. At this current time, that location stores a value of 3
, but if we were to assign a different value to x
, the location would remain the same–we would just replace the value at the location.
If we think about our variables as locations instead of values, we have some interesting ramifications–this comes back to the reference Vs. value discussion layed out in class
es Vs. struct
s. If we can find out where a value is stored in memory, we can pass that location to multiple locations and edit it from two places.
Note this is not valid code–it's just a demonstration of the concept.
This idea of passing a location, or to be more granular with terminology, a pointer to that location, is pretty prevalent in object-oriented languages.
Inout
OCaml programmers, think ref
s without dereferencing.
The most common time we want to use pointers in Swift is in functions. Otherwise, you can usually just access the variable. If you'll remember from functions, we can't simply modify the values in our parameters because they have been copied into let-constants. If we are dealing with reference types, you can, of course, just change its properties. But otherwise, we must explicitly tell the program that we want to preserve the location of the original variable with the inout
label.
Note that when we pass in an argument to this function, we must preserve it's location using a prefix &
:
A great use for this is in static
methods. The +=
operator needs to be able to get the value of a variable and assign to it. This means that its LHS parameter must be mutable!
To illustrate this, I will add +=
and ++
to the Int
eger class. +=
is already, but oh well ¯_(ツ)_/¯.
Okay, so +=
. We need to make our LHS mutable _ lhs: inout Int
, and take in an integer constant on the right side _ rhs: Int
. Since we are assigning it to a variable, all of our changes will be stored in the LHS and we will not need to return anything. Thus, our function declaration should look like static func += (_ lhs: inout Int, _ rhs: Int)
. The rest is self-explanatory.
To do ++
we do the exact same process except we are operating on one parameter. This means our function will not be infix
, so we must define it to either be prefix (before the parameter) or postfix (after the parameter).
Note that since this is a unary/binary operator, we don't need to use the &
to denote locations.
Last updated