Swift笔记 - 05.结构体、类
Swift笔记 - 05.结构体、类
结构体与类的本质区别
- 结构体是值类型(枚举也是值类型),类是引用类型(指针类型)
class Size {
var width = 1
var height = 2
}
struct Point {
var x = 3
var y = 4
}
func test() {
var size = Size()
var point = Point()
}
- 值类型的赋值操作
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(al) // $2, 2, 3]
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": 21]
print(d2) // ["max": 12, "min": 2]
- 在
Swift
标准中,为了提升性能,String
、Array
、Dictionary
、Set
采取了Copy On Write - 比如仅当有”写”操作时,才会真正执行拷贝操作
- 对于标准库值类型的赋值操作,
Swift
能确保最佳性能,所有没必要为了保证最佳性能来避免赋值 - 建议:不需要修改的,尽量定义成
let
寄存器
有16个常用寄存器
- rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp
- r8, r9, r10, r11, r12, r13, r14, r15
寄存器的具体用途
- rax常作为函数返回值使用
- rdi、rsi、rdx、rcx、r8、r9等寄存器常用于存放函数参数
- rsp、rbp用于栈操作
-
rip作为指令指针
- 存储着CPU下一条要执行的指令的地址
-
一旦CPU读取一条指令,rip会自动指向下一条指令(存储下一条指令的地址)
- 内存地址格式为:0x4bdc(%rip),一般是全局变量,全局区(数据段)
- 内存地址格式为:-0x78(%rbp),一般是局部变量,栈空间
- 内存地址格式为:0x10(%rax),一般是堆空间
闭包表达式
在Swift中,可以通过func
定义一个西数,也可以通过闭包表达式定义一个函数
func sum(_ v1: Int, v2: Int) -> Int ( v1 + v2 }
var fn = { (v1: Int, v2: Int) -> Int in
return vl + v2
}
fn(10, 20)
{
(参数列表)-> 返回值类型 in
}
{
(v1: Int, v2: Int) -> Int in
return v1 + v2
}(10, 20)
闭包表达式的简写
func exec(v1: Int, v2: Int, fn: (Int, Int) -> Int) {
print(fn(v1, v2))
}
exec(v1: 10, v2: 20, fn: {
(v1: Int, v2: Int) -> Int in
return v1 + v2
})
exec(v1: 10, v2: 20, fn: { $0 + $1 })
exec(v1: 10, v2: 20, fn: +)
exec(v1: 10, v2: 20, fn: {
v1,v2 in return v1 + v2
})
exec(v1: 10, v2: 20, fn: {
v1, v2 in v1 + v2
})
数组的排序
func sort(by areInIncreasingürder: (Element, Element) -> Bool)
// 返回true: i1 排在 i2 前面
// 返回false: i1 排在 i2 后面
func cmp(i1: Int, i2: Int) -> Bool {
// 大的排在前面
return i1 > i2
}
var nums = [11, 2, 18, 6, 5, 68, 45]
nums.sort(by: cmp)
// [68, 45, 18, 11, 6, 5, 21
nums.sort (by: {
(i1: Int, i2: Int) -> Bool in
return i1 < i2
})
nums.sort(by: { i1, i2 in return i1 < i2 })
nums.sort(by: { i1, i2 in i1 < i2 })
nums.sort(by: { $0 < $1 })
nums.sort(by: < )
nums.sort(){ $0 < $1 }
nums.sort{ $0 > $1 }
// 12, 5, 6, 11, 18, 45, 681
闭包
网上有各种关于闭包的定义,个人觉得比较严谨的定义是
- 一个函数和已所捕软的交量\常量环境组合起来,称为闭包
- 一般指定义在函数内部的函数
- 一般它捕获的是外层函数的局部变量/常量
可以把闭包想魚成是一个类的实例对象
- 内存在排空间
- 排获的局部变量\常量就是对象的成员(存储属性)
- 组成闭包的函数就是类内部定义的方法
typealias Fn = (Int) -> Int
func getFn() -> Fn {
var num = 0
func plus(_ i: Int) -> Int {
num += 1
return num
}
return plus
} //近日的plus和num形成了闭包
func getFn() -> Fn {
var num = 0
return {
num += $0
return num
}
}
var fn1 = getFn()
var fn2 = getFn()
fn1(1) //1
fn2(2) //2
fn1(3) //4
fn2(4) //6
fn1(5) //9
fn2(6) //12
class Closure {
var num = 0
func plus(_ i: Int) -> Int {
num += 1
return num
}
}
var cs1 = Closure()
var cs2 = Closure()
cs1.plus(1) // 1
cs2.plus(2) // 2
cs1.plus(3) // 4
cs2.plus(4) // 6
cs1.plus(5) // 9
cs2.plus(6) // 12
typealias Fn = (Int) -> (Int, Int)
func getFns() -> (Fn, Fn) {
var num1 = 0
var num2 = 0
func plus(_ i: Int) -> (Int, Int) {
num1 += i
num2 += i << 1
return (num1, num2)
}
func minus(i: Int) -> (Int, Int) {
num1 -= i
num2 -= i << 1
return (num1, num2)
}
return (plus, minus)
}
class Closure {
var num1 = 0
var num2 = 0
func plus(_ i: Int) -> (Int, Int) {
num1 += i
num2 += 1 << 1
return (num1, num2)
}
func minus(_ i: Int) -> (Int, Int) {
num1 -= i
num2 -= i << 1
return (num1, num2)
}
}
let (p, m) = getFns()
p(5) // (5, 10)
m(4) // (1, 2)
p(3) // (4, 8)
m(2) // (2, 4)
var cs = Closure()
cs.plus(5) // (5, 10)
cs.minus(4) // (1, 2)
cs.plus(3) // (4, 8)
cs.minus(2) // (2, 4)
var functions: [() -> Int] = []
for i in 1...3 {
functions.append { i }
}
for f in functions {
print(f())
}
class Closure {
var i: Int
init( i: Int) {
self.i = i
}
func get() -> Int {
return i
}
}
var clses: [Closure] = []
for i in 1...3 {
clses.append(Closure(i))
}
for cls in clses {
print(cls.get())
}
自动闭包
@autoclosure
会自动将20封装成闭包{20}
@autoclosure
只支持() -> T
格式的参数@autoclosure
并非只支持最后1个参数- 空合并运算符 ?? 使用了
@autoclosure
技术 - 有
@autoclosure
、无@autoclosure
,构成了函数重载 - 为了避免与期望冲突,使用了
@autoclosure
的地方最好明确注释清楚:这个值会被推迟执行
//如果第1个数大于8,返回第一个数,否则返回第2个数
func getFirstPositive(_ v1: Int,_ v2:Int) -> Int {
return v1 > 0 ? v1 : v2
}
getfirstPositive(10, 20) // 10
getFirstPositive(-2, 20) // 20
getFirstPositive(0, -4) // -4
//改成西数类型的參数,可以让v2延迟加载
func getFirstPositive(_ v1: Int,v2: () -> Int) -> Int? {
return v1 > 0 ? v1 : v2()
}
getFirstPositive(-4){ 20 }
func getFirstPositive(_ v1: Int, _ v2: @autoclosure () -> Int) -> Int? {
return v1 > 0 ? v1 : v20)
}
getFirstPositive(-4, 20)