欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Swift可選值優(yōu)化示例詳解

 更新時(shí)間:2023年06月19日 11:46:15   作者:云音樂(lè)技術(shù)團(tuán)隊(duì)  
這篇文章主要為大家介紹了Swift可選值優(yōu)化示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

nil 的語(yǔ)義

在 Objective-C 中,nil 表示空對(duì)象,它本質(zhì)是一個(gè)指向 0x00000000 的指針。但對(duì)于非指針的值類(lèi)型,OC 中是無(wú)法表示_沒(méi)有值_這個(gè)概念的,比如 NSInteger,它可以是 0,也可以是其他任何值,但就是不存在_沒(méi)有值_。

Swift 作為一種強(qiáng)類(lèi)型的語(yǔ)言,它從一開(kāi)始就引入了_沒(méi)有值_這個(gè)概念,雖然還是用 nil 關(guān)鍵字,但實(shí)際語(yǔ)義上有所不同。比如 Int?,它可以是 nil,也可以是 0,0 是一個(gè)具體的值,而 nil 不是。然而,計(jì)算機(jī)作為一個(gè)二進(jìn)制的機(jī)器,它內(nèi)存中保存的非 0 即 1,如何表示_沒(méi)有值_呢?換句話說(shuō),nil 在內(nèi)存中究竟是什么?我們可以通過(guò)簡(jiǎn)單的代碼找出它在內(nèi)存中的真相。

nil 在內(nèi)存中的表示

/// 以下方法取 value 的地址,并從地址處向后取它在內(nèi)存中的大小 size 個(gè)字節(jié),轉(zhuǎn)為對(duì)應(yīng)的數(shù)組
func bytes<T>(of value: T) -> [UInt8] {
    var value = value
    let size = MemoryLayout<T>.size
    return withUnsafePointer(to: &value, {
        $0.withMemoryRebound(
            to: UInt8.self,
            capacity: size,
            {
                Array(UnsafeBufferPointer(
                    start: $0, count: size))
            })
    })
}
var int: Int? = 0
bytes(of: int)    // [0, 0, 0, 0, 0, 0, 0, 0, 0]
int = nil
bytes(of: int)    // [0, 0, 0, 0, 0, 0, 0, 0, 1]

從上面我們可以得知,可選的 Int? 類(lèi)型比普通 Int 類(lèi)型多占一個(gè)字節(jié),用來(lái)表示是不是 沒(méi)有值。如果這樣的話,在 struct 或 class 中用可選類(lèi)型豈不是會(huì)浪費(fèi)較多內(nèi)存空間?因?yàn)閮?nèi)存對(duì)齊的緣故,多一個(gè)字節(jié),就要浪費(fèi)剩下的 7 字節(jié),比如:

struct N {
    var b: Int? = 2
    var a: Int? = 3
}
var n = N()
bytes(of: n)    // [2, 0, 0, 0, 0, 0, 0, 0, 0, 76, 68, 3, 1, 0, 0, 0, 
                //  3, 0, 0, 0, 0, 0, 0, 0, 0]

以上原本可以用 16 字節(jié)表示的結(jié)構(gòu)體,實(shí)際上占了 25 字節(jié)(考慮結(jié)尾處內(nèi)存對(duì)齊,其實(shí)占了 32 字節(jié))。我們?cè)趯?shí)際開(kāi)發(fā)中,可能會(huì)在 class 中聲明大量的可選字段,如果都這樣的話,那內(nèi)存使用率也太低了,有優(yōu)化手段嗎?

答案是有的,而且 Swift 編譯器已經(jīng)默默幫我們做了。

nil 的優(yōu)化

Bool

Bool 類(lèi)型理論上只用 0 1 兩個(gè)值,一個(gè) bit 即可,但它卻占了一整個(gè) byte ,剩下的幾個(gè) bit 是可以用來(lái)區(qū)分是否有值的。

var b: Bool? = false
bytes(of: b) // [0]
b = true
bytes(of: b) // [1]
b = nil
bytes(of: b) // [2]

從以上結(jié)果得知,Swift 用 2 表示 Bool? 的_沒(méi)有值_,所以沒(méi)有內(nèi)存浪費(fèi)。這樣也使得 Bool? 不再是兩態(tài)的開(kāi)關(guān),而是一個(gè)三態(tài)的開(kāi)關(guān)。于是經(jīng)常在代碼中看到看起來(lái)比較蠢的寫(xiě)法:

var value: Bool?
if value == true {
}

因?yàn)橐话銇?lái)說(shuō)是不建議 Bool 值與 true 判斷等的,它本身已經(jīng)是 Bool 了。而在 Swift 中又用起來(lái)是那么自然……

String

String 類(lèi)型不同于 Int 這種——0 也是合法值,String 的內(nèi)存值為 0 是可以表示_沒(méi)有值_的,所以它也沒(méi)有內(nèi)存浪費(fèi)

String 在 Swift 中是一個(gè)結(jié)構(gòu)體,無(wú)論字符串多長(zhǎng),String 變量本身只占 16 字節(jié),短的字符串通過(guò)類(lèi)似 OC 中 Tagged Pointer 的技術(shù)直接存在指針中,長(zhǎng)的字符串需要指向堆內(nèi)存地址。

Class

Class 類(lèi)型同 OC 中的一樣,是指針類(lèi)型,空指針可以表示_沒(méi)有值_,沒(méi)有內(nèi)存浪費(fèi)。

class MyObject {
    var b: Int? = 2
    var a: Int? = 3
}
var o: MyObject? = .init()
bytes(of: o)  // [160, 142, 188, 2, 0, 96, 0, 0]
o = nil
bytes(of: o)  // [0, 0, 0, 0, 0, 0, 0, 0]

無(wú)論 Class 中有多少成員變量,Class 變量本身(即指向它的指針)只占 8 字節(jié)(64位系統(tǒng)中)。

Enum

枚舉類(lèi)型一般是有限的,最終總可以找到一個(gè)不在枚舉范圍內(nèi)的值表示 _沒(méi)有值_,也可以沒(méi)有內(nèi)存浪費(fèi)。

enum Edge {
    case left
    case right
    case top
    case bottom
}
var e: Edge? = .left
bytes(of: e)  // [0]
e = .bottom
bytes(of: e)  // [3]
e = nil
bytes(of: e)  // [4],用越界值表示 nil,沒(méi)有值

當(dāng)然并不是所有 Enum 類(lèi)型都能這樣,帶關(guān)聯(lián)值的就可能不行。

結(jié)語(yǔ)

綜上所述,Swift 編譯器會(huì)盡可能地優(yōu)化可選值的內(nèi)存占用,日常開(kāi)發(fā)并不需要太多關(guān)心,但是部分情況仍要求開(kāi)發(fā)者盡量少使用可選值,如結(jié)構(gòu)體中連續(xù)幾個(gè)可選 Int 的情況,如果 0 也能滿(mǎn)足代碼邏輯,就使用非可選值,并用 0 初始化它吧!

// 浪費(fèi)的內(nèi)存比較可觀
struct My {
   var a: Int?
   var b: Int?
   var c: Int?
   var d: Int?
}

以上就是Swift可選值優(yōu)化示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Swift可選值優(yōu)化的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Swift實(shí)現(xiàn)監(jiān)聽(tīng)鍵盤(pán)通知及一些處理詳解

    Swift實(shí)現(xiàn)監(jiān)聽(tīng)鍵盤(pán)通知及一些處理詳解

    這篇文章主要給大家介紹了關(guān)于Swift實(shí)現(xiàn)監(jiān)聽(tīng)鍵盤(pán)通知及一些處理的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01
  • Swift利用AFN實(shí)現(xiàn)封裝網(wǎng)絡(luò)請(qǐng)求詳解

    Swift利用AFN實(shí)現(xiàn)封裝網(wǎng)絡(luò)請(qǐng)求詳解

    網(wǎng)絡(luò)請(qǐng)求工具是我們經(jīng)常用到的工具類(lèi),所以下面這篇文章主要給大家介紹了關(guān)于Swift利用AFN如何實(shí)現(xiàn)封裝網(wǎng)絡(luò)請(qǐng)求的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-10-10
  • swift 字符串String的使用方法

    swift 字符串String的使用方法

    這篇文章主要介紹了swift 字符串String的使用方法的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • Swift自定義UITableViewCell背景色

    Swift自定義UITableViewCell背景色

    這篇文章主要為大家詳細(xì)介紹了Swift自定義UITableViewCell背景色,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • 深入理解Swift中的訪問(wèn)控制關(guān)鍵字

    深入理解Swift中的訪問(wèn)控制關(guān)鍵字

    這篇文章主要給大家介紹了Swift中訪問(wèn)控制關(guān)鍵字的相關(guān)資料,文中介紹的非常詳細(xì),對(duì)大家具有一定的參考價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-03-03
  • Swift 中閉包的簡(jiǎn)單使用

    Swift 中閉包的簡(jiǎn)單使用

    這篇文章主要介紹了Swift 中閉包的簡(jiǎn)單使用的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • SwiftUI智能家居開(kāi)關(guān)燈頁(yè)面搭建示例

    SwiftUI智能家居開(kāi)關(guān)燈頁(yè)面搭建示例

    這篇文章主要為大家介紹了SwiftUI智能家居開(kāi)關(guān)燈頁(yè)面搭建示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Swift讓輸入框跟隨鍵盤(pán)彈起避免輸入輸入法擋住輸入框問(wèn)題

    Swift讓輸入框跟隨鍵盤(pán)彈起避免輸入輸入法擋住輸入框問(wèn)題

    這篇文章主要介紹了Swift讓輸入框跟隨鍵盤(pán)彈起避免輸入輸入法擋住輸入框問(wèn)題的完美解決方案,本文分步驟給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2016-11-11
  • EvenLoop模型在iOS的RunLoop應(yīng)用示例

    EvenLoop模型在iOS的RunLoop應(yīng)用示例

    這篇文章主要為大家介紹了EvenLoop模型在iOS的RunLoop應(yīng)用示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • Swift的開(kāi)發(fā)環(huán)境搭建以及基本語(yǔ)法詳解

    Swift的開(kāi)發(fā)環(huán)境搭建以及基本語(yǔ)法詳解

    這篇文章主要介紹了Swift的開(kāi)發(fā)環(huán)境搭建以及基本語(yǔ)法詳解,是Swift入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-11-11

最新評(píng)論