swift

《Swift从入门到精通》(二十二):内存安全

2021-10-20  本文已影响0人  萧1帅

内存安全(Memory Safety)(学习笔记)

环境Xcode 11.0 beta4 swift 5.1
欢迎留言 pen me

内存安全01 内存安全02
```swift
// 解决冲突的方法
// Make an explicit copy.
var copyOfStepSize = stepSize
increment(&copyOfStepSize)
// Update the original.
stepSize = copyOfStepSize
// stepSize is now 2

*   将同一个变量作为同一个函数的多个 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)
    // Error: conflicting accesses to playerOneScore

    ```

*   **方法内访问`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.shareHealth(with: &Oscar)
        // Error: conflicting accesses to oscar 如下下图

        ```

![内存安全03](https://img.haomeiwen.com/i6935167/407ed76482b682f4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![内存安全04](https://img.haomeiwen.com/i6935167/a485843a1fdaaf96.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

*   **访问属性时冲突**

    *   像结构体、元组、枚举是独立的值,因为它们是值类型,读或者写都是整一块内存的访问,如下访问元组的元素

    ```
    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
    // 但下面的情况是可以的,如果上面的变量 holly 是局部变量而不是全局变量,编译器可以证明这种重复访问是安全的,因为两个存储属性的内存不可能有交叉
    func someFunction() {
        var oscar = Player(name: "Oscar", health: 10, energy: 10)
        balance(&oscar.health, &oscar.energy)  // OK
    }

    ```

    *   当满足以下几点时,SWift编译器可以保证重复访问结构体属性时是安全的
    *   只访问存储属性,不访问计算属性和类型属性
    *   结构体变量是一个局部变量,非全局变量
    *   结构体既没有被闭包捕获也没有非逃逸闭包捕获


上一篇 下一篇

猜你喜欢

热点阅读