一、do 局部作用越
do {
let dog1 = Dog ()
dog1.age = 10
dog1. run ( )
}
do{
let dog2 = Dog ()
dog2.age = 10
dog2. run ()
}
二、内存访问冲突(Conflicting Access to Memory)
内存访问冲突会在两个访问满足下列条件时发生:
至少一个是写入操作
它们访问的是同一块内存
它们的访问时间重叠(比如在同一个函数内)
// 不存在内存访问冲突
func plus(_ num: inout Int) -> Int { num + 1 } var number = 1
number = plus(&number)
// 存在内存访问冲突
// Simultaneous accesses to 0x0, but modification requires exclusive access
var step = 1
func increment(_ num: inout Int) { num += step }
increment(&step)
// 解决内存访问冲突
var copyOfStep = step increment(©OfStep) step = copyOfStep
如果下面的条件可以满足 ,就说明重叠访问结构体的属性是安全的
你只访问实例存储属性,不是计算属性或者类属性
结构体是局部变量而非全局变量
结构体要么没有被闭包捕获要么只被非逃逸闭包捕获
// Ok
func test() {
var tulpe = (health: 10, energy: 20)
balance(&tulpe.health, &tulpe.energy)
var holly = Player(name: "Holly", health: 10, energy: 10)
balance(&holly.health, &holly.energy)
}
test()
三、指针
3.1 指针的应用示例
3.2 获得指向某个变量的指针
var age = 11
var ptr1 = withUnsafeMutablePointer(to: &age) { $0 }
var ptr2 = withUnsafePointer(to: &age) { $0 }
ptr1.pointee = 22
print(ptr2.pointee) // 22
print(age) // 22
范型指针转为非范型指针
var ptr3 = withUnsafeMutablePointer(to: &age) { UnsafeMutableRawPointer($0) }
var ptr4 = withUnsafePointer(to: &age) { UnsafeRawPointer($0) }
ptr3.storeBytes(of: 33, as: Int.self)
print(ptr4.load(as: Int.self)) // 33
print(age) // 33
3.3 获得指向堆空间实例的指针
class Person {}
var person = Person()
var ptr = withUnsafePointer(to: &person) { UnsafeRawPointer($0) }
var heapPtr = UnsafeRawPointer(bitPattern: ptr.load(as: UInt.self))
print(heapPtr!)
使用列子 :mems 的封装
3.3 创建指针
var ptr = UnsafeRawPointer(bitPattern: 0x100001234)
// 创建
var ptr = malloc(16)
// 存
ptr?.storeBytes(of: 11, as: Int.self)
ptr?.storeBytes(of: 22, toByteOffset: 8, as: Int.self)
// 取
print((ptr?.load(as: Int.self))!) // 11
print((ptr?.load(fromByteOffset: 8, as: Int.self))!) // 22 // 销毁
free(ptr)
var ptr = UnsafeMutableRawPointer.allocate(byteCount: 16, alignment: 1)
ptr.storeBytes(of: 11, as: Int.self)
ptr.advanced(by: 8).storeBytes(of: 22, as: Int.self)
print(ptr.load(as: Int.self)) // 11
print(ptr.advanced(by: 8).load(as: Int.self)) // 22
ptr.deallocate()
var ptr = UnsafeMutablePointer<Int>.allocate(capacity: 3)
ptr.initialize(to: 11)
ptr.successor().initialize(to: 22)
ptr.successor().successor().initialize(to: 33)
print(ptr.pointee) // 11
print((ptr + 1).pointee) // 22
print((ptr + 2).pointee) // 33
print(ptr[0]) // 11
print(ptr[1]) // 22
print(ptr[2]) // 33
ptr.deinitialize(count: 3)
ptr.deallocate()
class Person {
var age: Int
var name: String
init(age: Int, name: String) {
self.age = age
self.name = name
}
deinit { print(name, "deinit") }
}
var ptr = UnsafeMutablePointer<Person>.allocate(capacity: 3)
ptr.initialize(to: Person(age: 10, name: "Jack"))
(ptr + 1).initialize(to: Person(age: 11, name: "Rose"))
(ptr + 2).initialize(to: Person(age: 12, name: "Kate"))
// Jack deinit
// Rose deinit
// Kate deinit
ptr.deinitialize(count: 3)
ptr.deallocate()
3.4 指针之间的转换
var ptr = UnsafeMutableRawPointer.allocate(byteCount: 16, alignment: 1)
ptr.assumingMemoryBound(to: Int.self).pointee = 11
(ptr + 8).assumingMemoryBound(to: Double.self).pointee = 22.0
print(unsafeBitCast(ptr, to: UnsafePointer<Int>.self).pointee) // 11
print(unsafeBitCast(ptr + 8, to: UnsafePointer<Double>.self).pointee) // 22.0
ptr.deallocate()
unsafeBitCast是忽略数据类型的强制转换 ,不会因为数据类型的变化而改变原来的内存数据
类似于C++中的reinterpret_cast
class Person {}
var person = Person()
var ptr = unsafeBitCast(person, to: UnsafeRawPointer.self)
print(ptr)