iOS Swift No.25 - 内存安全2

第二十五章 内存安全

3. Conflicting Access to self in Methods (方法中的self冲突访问)

在方法调用期间,结构体中的可变方法有一个写入访问给self的,举个例子,考虑我们在玩一个游戏,每一个玩家都有一定量的健康值,收到攻击健康值就会减少,使用特殊技能能量值就会增加,

struct Player {
    var name: String
    var health: Int
    var energy: Int

    static let maxHealth = 10
    mutating func restoreHealth() {
        health = Player.maxHealth
    }
}

在上面的restoreHealth()方法中,一个给self的写入访问起始于方法开始一直持续到该方法返回。在这种情况下,restoreHealth()里面并没有其他代码。可能会有一个给Player实例属性的重叠访问。下面的这个shareHealth(with:)方法采用了另一个Player的实例作为一个输入输出型参数,创建了一个有可能的重叠访问。

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玩家和Maria玩家创建了一个shareHealth(with:)方法并不会产生冲突,当我们调用该方法的时候给Oscar玩家的只有一个写入访问,因为Oscar玩家在可变方法中是一个self的值。在相同期间另一个给maria写入访问也在进行。因为maria是以输入输出型参数传入的。下面的图例可以详细说明。它们访问的是内存中的不同位置。即便是他们的访问时间或者期间是重叠的,并不会产生冲突。
在这里插入图片描述

然而当我们将oscar以参数的形式传入给shareHealth(with:)方法时,会产生冲突。

oscar.shareHealth(with: &oscar)
// Error: conflicting accesses to oscar

可变方法需要在该方法访问持续时间内需要一个给self的写入访问,并且相同访问持续时间内另一个输入输出型参数要对teammate有一个写入访问,在同一个方法内self和teammate指向的是内存中相同的位置。见下图列。两个写入访问在同一个方法里指向了内存中的同一个位置,所以这样就会产生冲突。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45026183/article/details/107925816
今日推荐