网站停留时间 从哪里获取欢迎访问中国建设银行网上银行网站

当前位置: 首页 > news >正文

网站停留时间 从哪里获取,欢迎访问中国建设银行网上银行网站,好看的seo网站,书法网站开发的前景内存的访问#xff0c;发生在给变量赋值的时候#xff0c;或者传递值#xff08;给函数#xff09;的时候#xff0c;例如 var one 1//向one的内存区域发起一次写的操作 print((one))//向one的内存区域发起一次读的操作 在 Swift 里#xff0c;有很多修改…内存的访问发生在给变量赋值的时候或者传递值给函数的时候例如 var one 1//向one的内存区域发起一次写的操作 print((one))//向one的内存区域发起一次读的操作 在 Swift 里有很多修改值的行为都会持续好几行代码在修改值的过程中进行访问是有可能发生的。读和写访问的区别很明显一个写访问会改变存储地址而读操作不会。存储地址是指向正在访问的东西例如一个变量常量或者属性的位置的值 。内存访问的时长要么是瞬时的要么是长期的。如果一个访问不可能在其访问期间被其它代码访问那么就是一个瞬时访问。正常来说两个瞬时访问是不可能同时发生的。大多数内存访问都是瞬时的。例如下面列举的所有读和写访问都是瞬时的 func oneMore(than number: Int) - Int {return number 1 }var myNumber 1 myNumber oneMore(than: myNumber) print(myNumber) // 打印“2” 然而有几种被称为长期访问的内存访问方式会在别的代码执行时持续进行。瞬时访问和长期访问的区别在于别的代码有没有可能在访问期间同时访问也就是在时间线上的重叠。一个长期访问可以被别的长期访问或瞬时访问重叠。如果发生了重叠访问就可能会造成内存冲突因为在同一块内存区域同时发生读和写的操作是肯定不被允许的。 重叠的访问主要出现在使用 in-out 参数的函数和方法或者结构体的 mutating 方法里。 In-Out 参数的访问冲突 一个函数会对它所有的 in-out 参数保持长期写访问。in-out 参数的写访问会在所有非 in-out 参数处理完之后开始直到函数执行完毕为止。如果有多个 in-out 参数则写访问开始的顺序与参数的顺序一致。 这种长期保持的写访问带来的问题是你不能再访问以 in-out 形式传入的原始变量即使作用域原则和访问权限允许——任何访问原始变量的行为都会造成冲突。例如 var stepSize 1func increment(_ number: inout Int) {number stepSizeprint(number)//不会产生读访问 }increment(stepSize) // 错误stepSize 访问冲突 代码中stepSize是一个全局变量并且我们以inout的形式将该变量传入了increment函数当中这里我们得知道的是一个函数会对它所有的 in-out 参数保持长期写访问inout参数的写访问会在所有非 in-out 参数处理完之后开始直到函数执行完毕为止。这种方法的带来的弊端就是你不能在访问以inout形式传入的原始变量我都得到地址了我还访问原始干嘛对吧即使作用域原则和访问权限允许——任何访问原始变量的行为都会造成冲突。上述代码中由于inout带来的长期写访问而我们也对stepSize进行了读访问。所以就会造成内存冲突。当然同一函数传入两个inout相同的数据也会造成写访问冲突但是为什么printnumber不回发生内存冲突呢实际上将inout传入进去时swift发生了以下操作 1. 写访问发生在调用期间• 变量 stepSize 被作为 inout 参数传递给 increment。• Swift 会暂时暂停对原始变量的所有访问并将其访问权转移给函数的 inout 参数 number。2. 对原变量的隔离• 在函数调用期间stepSize 被隔离外部无法访问。• 任何对 number 的读写操作都会作用于 stepSize 的值但此时只通过 number 访问变量。3. 生命周期的非交叠• 函数调用开始时stepSize 的值被写入到 number 的内存。• 在函数调用结束时number 的值被写回到 stepSize。• 在调用期间stepSize 不再直接可用因此不存在交叠访问。 解决冲突的方式很多这里举例一种很鸡肋的方式 // 显式拷贝 var copyOfStepSize stepSize increment(copyOfStepSize)// 更新原来的值 stepSize copyOfStepSize // stepSize 现在的值是 2 方法里self带来访问冲突 废话少说上图 struct Player {var name: Stringvar health: Intvar energy: Intstatic let maxHealth 10mutating func restoreHealth() {health Player.maxHealth} }extension Player {mutating func shareHealth(with teammate: inout Player) {balance(teammate.health, health)} }var oscar Player(name: Oscar, health: 10, energy: 10) var maria Player(name: Maria, health: 5, energy: 10) oscar.shareHealth(with: maria) // 正常 oscar.shareHealth(with: Oscar) // 错误oscar 访问冲突在上述代码中我们在plyer结构题方法中对restoreHealth使用mutating访问权限这样就会一直有对self的写访问而在oscar.shareHealth我们传入了oscar,shareHealth中的inout又对Player进行的写访问就造成了两个写访问冲突。所以会造成内存 var holly Player(name: Holly, health: 10, energy: 10) balance(holly.health, holly.energy) // 错误 崩溃。有人疑惑为什么上面的restoreHealth()中不会发生内存冲突呢 我们可以看到maxHealth我们是是用static静态修饰的他属于类型本身而不属于任何实例他储单独存储在静态区域。所以访问自然与实例无关了。 属性的访问冲突 如结构体元组和枚举的类型都是由多个独立的值组成的例如结构体的属性或元组的元素。因为它们都是值类型修改值的任何一部分都是对于整个值的修改意味着其中一个属性的读或写访问都需要访问一整个值。例如元组元素的写访问重叠会产生冲突 var playerInformation (health: 10, energy: 20) balance(playerInformation.health, playerInformation.energy) // 错误playerInformation 的属性访问冲突 在结构体中下面展示了对于一个存储在全局变量里的结构体属性的写访问重叠了。 var holly Player(name: Holly, health: 10, energy: 10) balance(holly.health, holly.energy) // 错误 但是对于本地变量编译器就可以编译器就可以保证重叠访问是安全的不懂但尊重。 func someFunction() {var oscar Player(name: Oscar, health: 10, energy: 10)balance(oscar.health, oscar.energy) // 正常 } 以下就是一些规则它可以保证结构体属性的重叠访问是安全的 ·你访问的是实例的存储属性而不是计算属性或类的属性 ·结构体是本地变量的值而非全局变量 ·结构体要么没有被闭包捕获要么只被非逃逸闭包捕获了