内存访问的特点
如果有两个访问动作出现在以下情况中,便会发生冲突
- 至少有一个动作是写入访问
- 访问的是同一块内存
- 访问的时间有重叠
访问内存分为即时的和长期的
- 即时的访问:如果其它代码在访问开始之后至结束之前无法运行,则访问是即时的。 所以,两个即时访问不能同时发生。 大部分内存访问是即时的。
以下所有的访问都是即时的
func oneMore(than number: Int) -> Int {
return number + 1
}
var myNumber = 1
myNumber = oneMore(than: myNumber)
print(myNumber)
// Prints "2"
- 长期的访问:其它代码可能在访问开始之后至结束之前运行,称为重叠(overlap),一个长期访问可以和另一个长期访问或即时访问重叠。
重叠访问:主要出现在函数的in-out参数和结构中的方法和可变方法中。
in-out参数的访问冲突
函数对它的in-out参数有写入的长期访问
不能对传递给in-out参数的变量有任何的访问,否则会产生冲突
var stepSize = 1
func incrementInPlace(_ number: inout Int) {
number += stepSize
}
incrementInPlace(&stepSize)
// Error: conflicting accesses to stepSize
不能把同一个变量传递给同一函数的不同in-out参数,否则会产生冲突
func balance(_ x: inout Int, _ y: inout Int) {
let sum = x + y
x = sum / 2
y = sum - x
}
var playerOneScore = 42
var playerTwoScore = 30
balance(&playerOneScore, &playerTwoScore) // OK
balance(&playerOneScore, &playerOneScore)
方法内self的访问冲突
一个可变方法调用时对self有长期访问
struct Player {
var name: String
var health: Int
var energy: Int
static let maxHealth = 10
mutating 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) // OK
未产生冲突
当传递oscar给参数时,会产生冲突
oscar.shareHealth(with: &oscar)
image.png
属性的访问冲突
结构体、元组和枚举的都是值类型,对类型中的值改变会改变整个值,所以对一个属性的读取或写入访问需要读取或写入访问整个值。
把变量传递给in-out参数,会在整个函数调用期间对变量有写入的访问,
下列例子对元组有两个定入的访问,所以会产生冲突。
var playerInformation = (health: 10, energy: 20)
balance(&playerInformation.health, &playerInformation.energy)
// Error: conflicting access to properties of playerInformation
全局的存储性结构体变量也会产生同样的错误
var holly = Player(name: "Holly", health: 10, energy: 10)
balance(&holly.health, &holly.energy) // Error
编译器会保证局部的结构体变量的重叠是安全的
func someFunction() {
var oscar = Player(name: "Oscar", health: 10, energy: 10)
balance(&oscar.health, &oscar.energy) // OK
}
满足以下条件的重叠是安全的
- 仅仅访问的实例的存储性属性,没有计算性属性和类属性
- 结构体是局部变量,不是全局变量
- 结构体要么不被闭包捕获,要么只能被nonescaping闭包捕获。
原文地址
网友评论