A struct is copied
Let's go back to the photocopier from the start of the theme. The form Point with x: 1 goes into the copier, and out comes a copy. On the copy, the field x is corrected to 10. The original does not change: it still reads x: 1.
A struct in Swift is copied the same way. Let's look at the code:
struct Point {
var x: Int
var y: Int
}
let a = Point(x: 1, y: 2)
var b = a
b.x = 10
print(a.x, b.x) // 1 10Let's walk through the program line by line:
let a = Point(x: 1, y: 2)fills in the original form.var b = amakes a copy: now there are two forms, with the same entries on them.b.x = 10corrects the field on the copy only.print(a.x, b.x)prints1 10: the original has not changed.
Notice that a is declared with let and b with var. The copy has its own declaration, so you can change it even though the original is a constant.
A struct is a value type
An array, as you already know, is a value type: an assignment creates an independent copy of it. A struct is a value type too. Most often its copy appears in two cases:
- on assignment:
var b = a; - on passing to a function: the parameter gets its own copy of the instance.
Press "Next step" and compare a with b, and then b with the points inside the function moved: only the instance whose property was corrected changes.
1struct Point {2 var x: Int3 var y: Int4}5 6func moved(_ p: Point) -> Point {7 var copy = p8 copy.x += 59 return copy10}11 12let a = Point(x: 1, y: 2)13var b = a14b.x = 1015print(a.x, b.x)16let c = moved(b)17print(b.x, c.x)
The constant a is the original form with x: 1 and y: 2.
The function moved gets a copy of b in the parameter p. A parameter is a constant, so the function makes one more copy, copy, changes it and returns it. After the call b is unchanged, and the point with x: 15 sits in c. For a function to change the caller's variable itself, you need an inout parameter and & at the call.
Here the photocopier picture is inaccurate. A paper copy is made by hand, when someone needs one. Swift copies a struct on its own, on every assignment and every pass to a function, with no separate "copy" command.
Interviewers like to ask: what happens to the first struct if you change its copy? The answer: nothing. A struct is a value type, and the copy has its own properties, independent of the original.
Common mistake
A point is taken out of an array, changed, and the array element is expected to change:
var points = [Point(x: 1, y: 2), Point(x: 3, y: 4)]
var first = points[0]
first.x = 10 // ✗
print(points[0].x) // 1The program compiles and prints 1. The line var first = points[0] creates a copy of the element, and first.x = 10 corrects only that copy, while the element in the array stays as it was. To change the element itself, write through the index: points[0].x = 10.
Key points
- A struct is a value type:
var b = acreates an independent copy, and changes tobare not seen ina. - A copy has its own declaration: a struct from a
letcan be copied into avarand changed. - A function gets its own copy of a struct, and changes inside the function do not touch the variable outside.
- A variable gets a copy of an array element; the element itself is changed through the index:
points[0].x = 10.