The structure of the body
- In the Swift standard library, the vast majority of exposed types are structures, while enumerations and classes make up only a small portion
Common types such as Bool, Int, Double, String, Array, and Dictionary are all structures
struct Date {
var year: Int
var month: Int
var day: Int
}
var date = Date(year: 2020, month:02, day:29)// The compiler automatically generates an initializer for the structure
Copy the code
- All structures have an initializer automatically generated by the compiler (initializer, initializer, constructor, constructor)
In line ⑥, you can pass in all the member values to initialize all the members.
Initializer for a structure
The compiler may generate multiple initializers for a structure, depending on the situation,The purpose is to ensure that all members have initial values and that the code is safe
Take a look at the following scenarios where an error is reported because a member variable is not initialized This way, there is no problem
struct Point {
var x: Int = 0
var y: Int = 0
}
var p1 = Point(x: 10, y: 10)
var p2 = Point(y: 10)
var p3 = Point(x: 10)
var p4 = Point(a)Copy the code
Let’s do another scene
struct Point {
var x: Int?
var y: Int?
}
var p1 = Point(x: 10, y: 10)
var p2 = Point(y: 10)
var p3 = Point(x: 10)
var p4 = Point(a)Copy the code
Because var x: Int? var y: Int? After the declaration, there is an initial value of nil by default, so the above error is not reported
Custom initializers
Once you define an initializer when defining a structure, the compiler does not automatically generate other initializers for it
Peep into the nature of the initializer
Here is the equivalent code at both ends. The first section uses the system-generated no-parameter initializer, and the second section uses our custom no-parameter initializer
struct Point {
var x: Int = 0
var y: Int = 0
}
var p = Point(a)Copy the code
struct Point {
var x: Int
var y: Int
init(a) {
x = 0
y = 0}}var p = Point(a)Copy the code
Let’s take a look at their assembly code
func testStruct(a) {
struct Point {
var x: Int = 0
var y: Int = 0
}
var p = Point(a)// Add a breakpoint here and run the program
}
testStruct()
* * * * * * * * * * * * * * *Assembly codeSwiftTest`init(a) in Point #1 in testStruct():
-> 0x1000010b0 <+0>: pushq %rbp
0x1000010b1 <+1>: movq %rsp, %rbp
0x1000010b4 <+4>: xorps %xmm0, %xmm0
0x1000010b7 <+7>: movaps %xmm0, -0x10(%rbp)
0x1000010bb <+11>: movq $0x0, -0x10(%rbp)
0x1000010c3 <+19>: movq $0x0, -0x8(%rbp)
0x1000010cb <+27>: xorl %eax, %eax
0x1000010cd <+29>: movl %eax, %ecx
0x1000010cf <+31>: movq %rcx, %rax
0x1000010d2 <+34>: movq %rcx, %rdx
0x1000010d5 <+37>: popq %rbp
0x1000010d6 <+38>: retq
Copy the code
func testStruct(a) {
struct Point {
var x: Int
var y: Int
init(a) {
x = 0
y = 0}}var p = Point(a)// Add a breakpoint here and run the program
}
testStruct()
* * * * * * * * * * * * * * *Assembly codeSwiftTest`init(a) in Point #1 in testStruct():
-> 0x1000010b0 <+0>: pushq %rbp
0x1000010b1 <+1>: movq %rsp, %rbp
0x1000010b4 <+4>: xorps %xmm0, %xmm0
0x1000010b7 <+7>: movaps %xmm0, -0x10(%rbp)
0x1000010bb <+11>: movq $0x0, -0x10(%rbp)
0x1000010c3 <+19>: movq $0x0, -0x8(%rbp)
0x1000010cb <+27>: xorl %eax, %eax
0x1000010cd <+29>: movl %eax, %ecx
0x1000010cf <+31>: movq %rcx, %rax
0x1000010d2 <+34>: movq %rcx, %rdx
0x1000010d5 <+37>: popq %rbp
0x1000010d6 <+38>: retq
Copy the code
Comparing the above two programs, the assembly code underlying the no-parameter initializer function they call is exactly the same, so it is equivalent. Grammar sugar may deceive, but assembly never will.
Structures exist within structures
struct Point {
var x: Int = 10
var y: Int = 20
var origin: Bool = true
}
var p = Point(a)print(MemoryLayout<Point>.size)
print(MemoryLayout<Point>.stride)
print(MemoryLayout<Point>.alignment)
print(Mems.memStr(ofVal: &p)) // Output the data stored in the structure
* * * * * * * * * * * * * * * *The results17
24
8
0x000000000000000a 0x0000000000000014 0x0000000000000001
Program ended with exit code: 0
Copy the code
It can be seen that the structure of Swift is the same as the structure of C language, and the memory of member variables are all close together
class
The definition of a class is similar to that of a structure, but the compiler does not automatically generate initializers for classes that can pass in member valuesIn each member of the classThere are
By default, a no-parameter initializer is created for itOne thing to notevar x: Int?
isoptional, so it automatically gets a default valuenil
. Compared withStruct.ClassThe statement is almost identical toStructExactly the same, you can also add methods internally. From the table, only the initializer is a little different.
Class initializer
Initialization of a member is done in this initializer. Here is the code that is exactly equivalent at both ends (same as above — assembly).
class Point {
var x: Int = 10
var y: Int = 20
}
let p = Point(a)Copy the code
class Point {
var x: Int
var y: Int
init(a) {
x = 10
y = 20}}let p = Point(a)Copy the code
Essential differences between structures and classes
Structs are value types (enumerations are also value types) and classes are reference types (pointer types)
class Size {
var width = 1
var height = 2
}
struct Point {
var x = 3
var y = 4
}
func test(a) {
var size = Size(a)var point = Point()}Copy the code
In the code abovesize
andpoint
The distribution in memory is as follows
Object heap space application process
Take a look at the following scenario
func testClassAndStruct(a) {
class Size {
var width = 1
var height = 2
}
struct Point {
var x = 3
var y = 4
}
var size = Size(a)//----- add a breakpoint here and run to open the assembly interface
//var point = Point()
}
testClassAndStruct()
Copy the code
To create an instance object of a class in Swift, the process is as follows
Class.__allocating_init()
- libswiftCore.dylib:
_swift_allocObject_
- libswiftCore.dylib:
swift_slowAlloc
- libsystem_malloc.dylib:
malloc
The malloc function on Mac and iOS always allocates a multiple of 16 memory size. Class_getInstanceSize tells you how much memory an object of your class actually uses
class Point {
var x = 11
var test = true
var y = 22
}
var p = Point(a)print(class_getInstanceSize(type(of: p))) / / 40
print(class_getInstanceSize(Point.self)) / / 40
Copy the code
Value types
- Value type assigned to
var
,let
Or you can just pass a parameter to a function, or you can just make a copy of everything
It’s like doing a filecopy
,paste
Operation produces a brand new copy of the file. Belong to deep copy (deep copy)
The assignment operation of a value type
- In the Swift standard library, to improve performance,
String
,Array
,Dictionary
,Set
To take theCopy On WriteThe technical- For example, a copy operation is performed only when there is a write operation
- Swift ensures optimal performance for assignment operations of library value types, so there is no need to avoid assignment in order to ensure optimal freshness
Note that this is for the Swift standard library only. Swift does not use Copy On Write for custom constructs
- Suggestion: If no modification is required, try to define it as
let
var s1 = "Jack"
var s2 = s1
s2.append("_Rose")
print(s1)//Jack
print(s2)//Jack_Rose
var a1 = [1.2.3]
var a2 = a1
a2.append(4)
a1[0] = 2
print(a1)//[1,3,4]
print(a2)/ / [1, 2, 3, 4]
var d1 = ["max": 10."min":2]
var d2 = d1
d1["other"] = 7
d2["max"] = 12
print(d1)//["other": 7, "max": 10, "min":2]
print(d2)//["max": 12, "min":2]
Copy the code
Reference types
- Reference assignment to
var
,let
Or to pass a parameter to a function, make a copy of the memory address
Similar to making a file substitute (shortcut, link) that points to the same file. Belongs to a shallow copy
class Size {
var width: Int
var height: Int
init(width: Int.height: Int) {
self.width = width
self.height = height
}
}
func test(a) {
var s1 = Size(width: 10, height: 20)
var s2 = s1
s2.width = 11
s2.height = 22
}
test()
Copy the code
An assignment operation of a reference type
class Size {
var width: Int
var height: Int
init(width: Int.height: Int) {
self.width = width
self.height = height
}
}
var s1 = Size(width: 10, height: 20)
s1 = Size(width: 11, height: 12)
Copy the code
Value type, reference type let
To summarize, let means that the contents of the memory space corresponding to the constant it modifies cannot be modified.
- Since all the members of a value type are in its memory, its internal members cannot be modified when it is modified by a let
- A reference type has only Pointers in memory, so the value of this pointer cannot be changed. However, the object instance that the pointer points to is not in the memory of the reference type. Therefore, after being modified by let, the value of the heapspace object can still be changed.
Nested types
struct Poker {
enum Suit: Character {
case spades = "️", heart = "️", diamonds = "️", clubs = "️"
}
enum Rand: Int {
case two = 2, three, four, five, six, seven, eight, nine, ten
case jack, queen, king, ace
}
}
print(Poker.Suit.heart.rawValue)
var suit = Poker.Suit.spades
suit = .diamonds
var rank = Poker.Rand.five
rank = .king
Copy the code
Enumerations, structures, and classes can all define methods
- Functions defined in enumerations, structures, and classes are generally called methods
class Size {
var width = 10
var height = 10
func show(a) {
print("width= \(width), height= \(height)")}}let s = Size()
s.show()
struct Point {
var x = 10
var y = 10
func show(a) {
print("x= \(x), y= \(y)")}}let p = Point()
p.show()
enum PokerFace: Character {
case spades = "️", heart = "️", diamonds = "️", clubs = "️"
func show(a) {
print("face is \(rawValue)")}}let pf = PokerFace.heart
pf.show()
Copy the code
- Do methods occupy memory objects?
- Do not take up
- Methods are essentially functions
- Methods and functions are placed in the code section