結(jié)構(gòu)體和類的區(qū)別

一、初始化方法不同

swift文件轉(zhuǎn)sil文件命令

swiftc -emit-sil main.swift > main.sil
swift:
struct LSPerson {
    var age : Int = 20
}

sil:
struct LSPerson {
  @_hasStorage @_hasInitialValue var age: Int { get set }
  init(age: Int = 20)
  init()
}
  1. 結(jié)構(gòu)體成員有默認(rèn)值時(shí)输瓜,編譯器自動(dòng)生成 init(age: Int = 20)init() (帶參和不帶參)的初始化方法
swift:
struct LSPerson {
    var age : Int
}

sil:
struct LSPerson {
  @_hasStorage var age: Int { get set }
  init(age: Int)
}
  1. 結(jié)構(gòu)體成員沒有默認(rèn)值時(shí)覆劈,編譯器只會自動(dòng)生成 init(age: Int) (帶參)的初始化方法
swift:
class LSPerson {
    var age: Int = 20
}

sil:
class LSPerson {
  @_hasStorage @_hasInitialValue var age: Int { get set }
  @objc deinit
  init()
}
  1. 類class 中如果所有成員變量都有默認(rèn)值甩卓,編譯器會自動(dòng)生成 init() (不帶參)的初始化方法
swift:
class LSPerson {
    var age: Int
    init(_ age: Int) {
        self.age = age
    }
}

sil:
class LSPerson {
  @_hasStorage var age: Int { get set }
  init(_ age: Int)
  @objc deinit
}
  1. 類class 中如果有成員變量沒有默認(rèn)值双肤,則必須自己聲明初始化方法弦聂,否則會編譯不通過,報(bào)錯(cuò)class has no initalizer

二柳击、值類型和引用類型

  • 結(jié)構(gòu)體:值類型
struct LSPerson {
    var age : Int = 20
}

var p = LSPerson()

var p1 = p
p1.age = 40

print("\(p.age)")
print("\(p1.age)")

打印結(jié)果為2040猿推,可以看到結(jié)構(gòu)體實(shí)例進(jìn)行賦值后,修改結(jié)構(gòu)體的成員變量的值捌肴,對其他結(jié)構(gòu)體實(shí)例中成員變量的值沒有影響蹬叭。

打印結(jié)構(gòu)體實(shí)例地址命令

po withUnsafeMutablePointer(to: &p){print($0)}
po withUnsafeMutablePointer(to: &p1){print($0)}
image.png
  1. 可以看到結(jié)構(gòu)體對象地址中存儲的是成員變量的值

同樣可以將swift文件轉(zhuǎn)成sil進(jìn)行查看

// LSPerson.init()
sil hidden @$s4main8LSPersonVACycfC : $@convention(method) (@thin LSPerson.Type) -> LSPerson {
// %0 "$metatype"
bb0(%0 : $@thin LSPerson.Type):
  %1 = alloc_stack $LSPerson, let, name "self"    // users: %4, %7
  %2 = integer_literal $Builtin.Int64, 20         // user: %3
  %3 = struct $Int (%2 : $Builtin.Int64)          // users: %5, %6
  %4 = struct_element_addr %1 : $*LSPerson, #LSPerson.age // user: %5
  store %3 to %4 : $*Int                          // id: %5
  %6 = struct $LSPerson (%3 : $Int)               // user: %8
  dealloc_stack %1 : $*LSPerson                   // id: %7
  return %6 : $LSPerson                           // id: %8
} // end sil function '$s4main8LSPersonVACycfC'
  1. LSPerson.init()結(jié)構(gòu)體初始化實(shí)例時(shí),是調(diào)用alloc_stack函數(shù)状知,是在棧上開辟空間創(chuàng)建變量秽五。
  • 類 class:引用類型
class LSPerson {
    var age: Int
    init(_ age: Int) {
        self.age = age
    }
}

var p = LSPerson(20)

var p1 = p
p1.age = 40

print("p.age=\(p.age)")
print("p1.age=\(p1.age)")

打印結(jié)構(gòu)為p.age=40p1.age=40,類的實(shí)例對象賦值后饥悴,修改新的實(shí)例對象中屬性的值坦喘,會影響就的類實(shí)例對象的值

  1. 在控制臺進(jìn)行打印,發(fā)現(xiàn)p和p1指向同一塊內(nèi)存西设,所以進(jìn)行修改會互相影響瓣铣。

同樣可以查看sil文件

// LSPerson.__allocating_init(_:)
sil hidden [exact_self_class] @$s4main8LSPersonCyACSicfC : $@convention(method) (Int, @thick LSPerson.Type) -> @owned LSPerson {
// %0 "age"                                       // user: %4
// %1 "$metatype"
bb0(%0 : $Int, %1 : $@thick LSPerson.Type):
  %2 = alloc_ref $LSPerson                        // user: %4
  // function_ref LSPerson.init(_:)
  %3 = function_ref @$s4main8LSPersonCyACSicfc : $@convention(method) (Int, @owned LSPerson) -> @owned LSPerson // user: %4
  %4 = apply %3(%0, %2) : $@convention(method) (Int, @owned LSPerson) -> @owned LSPerson // user: %5
  return %4 : $LSPerson                           // id: %5
} // end sil function '$s4main8LSPersonCyACSicfC'

LSPerson.__allocating_init(_:)初始化方法中,調(diào)用alloc_ref函數(shù)贷揽,應(yīng)該是在堆上進(jìn)行內(nèi)存分配棠笑,然后將指針p指向該內(nèi)存。

三禽绪、方法調(diào)用方式不同

  • 結(jié)構(gòu)體方法調(diào)用
struct LSPerson {
    func eat() {
        print("eat")
    }
}

var p = LSPerson()
p.eat()

p.eat()處打斷點(diǎn)查看匯編代碼如下圖所示

image.png

可以看到調(diào)用eat方法蓖救,是直接調(diào)用callq 0x100002b70洪规,靜態(tài)調(diào)用。

image.png

使用MachOView查看macho文件循捺,在匯編代碼部分淹冰,同樣可以直接看到調(diào)用0x100002b70該地址。

image.png

Symbol Tables中巨柒,可以同樣找到對應(yīng)地址的函數(shù)樱拴。Symbol Tables中的符號地址代表,符號在字符串表String Tables中的偏移位置洋满。

  1. 結(jié)論是結(jié)構(gòu)體在編譯鏈接之后晶乔,其中的方法地址已經(jīng)確定了,通過靜態(tài)調(diào)用效率更高
  • 類 class的方法調(diào)用
    //TODO

結(jié)構(gòu)體和類的區(qū)別總結(jié):
一牺勾、初始化方法不同

  1. 結(jié)構(gòu)體成員有默認(rèn)值時(shí)正罢,編譯器自動(dòng)生成 init(age: Int = 20)init() (帶參和不帶參)的初始化方法。
  2. 結(jié)構(gòu)體成員沒有默認(rèn)值時(shí)驻民,編譯器只會自動(dòng)生成 init(age: Int) (帶參)的初始化方法翻具。
  3. 類class 中如果所有成員變量都有默認(rèn)值,編譯器會自動(dòng)生成 init() (不帶參)的初始化方法回还。
  4. 類class 中如果有成員變量沒有默認(rèn)值裆泳,則必須自己聲明初始化方法,否則會編譯不通過柠硕,報(bào)錯(cuò)class has no initalizer工禾。

二、值類型和引用類型

  • 結(jié)構(gòu)體
  1. 結(jié)構(gòu)體是值類型蝗柔。
  2. 結(jié)構(gòu)體對象地址中存儲的是成員變量的值闻葵。
  3. 結(jié)構(gòu)體初始化實(shí)例時(shí),是調(diào)用alloc_stack函數(shù)癣丧,是在棧上開辟空間創(chuàng)建變量槽畔。
  1. 類是引用類型。
  2. 類初始化實(shí)例時(shí)胁编,調(diào)用alloc_ref函數(shù)厢钧,是在堆上進(jìn)行內(nèi)存分配,然后將指針p指向該內(nèi)存掏呼。

三坏快、方法調(diào)用方式不同

  1. 結(jié)構(gòu)體在編譯鏈接之后铅檩,其中的方法地址已經(jīng)確定了憎夷,通過靜態(tài)調(diào)用效率更高
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市昧旨,隨后出現(xiàn)的幾起案子拾给,更是在濱河造成了極大的恐慌祥得,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蒋得,死亡現(xiàn)場離奇詭異级及,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)额衙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門饮焦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人窍侧,你說我怎么就攤上這事县踢。” “怎么了伟件?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵硼啤,是天一觀的道長。 經(jīng)常有香客問我斧账,道長谴返,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任咧织,我火速辦了婚禮嗓袱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘习绢。我一直安慰自己索抓,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布毯炮。 她就那樣靜靜地躺著逼肯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪桃煎。 梳的紋絲不亂的頭發(fā)上篮幢,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天,我揣著相機(jī)與錄音为迈,去河邊找鬼三椿。 笑死,一個(gè)胖子當(dāng)著我的面吹牛葫辐,可吹牛的內(nèi)容都是我干的搜锰。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼耿战,長吁一口氣:“原來是場噩夢啊……” “哼蛋叼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤狈涮,失蹤者是張志新(化名)和其女友劉穎狐胎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體歌馍,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡握巢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了松却。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片暴浦。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖晓锻,靈堂內(nèi)的尸體忽然破棺而出肉渴,到底是詐尸還是另有隱情,我是刑警寧澤带射,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布同规,位于F島的核電站,受9級特大地震影響窟社,放射性物質(zhì)發(fā)生泄漏券勺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一灿里、第九天 我趴在偏房一處隱蔽的房頂上張望关炼。 院中可真熱鬧,春花似錦匣吊、人聲如沸儒拂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽社痛。三九已至,卻和暖如春命雀,著一層夾襖步出監(jiān)牢的瞬間蒜哀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工吏砂, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留撵儿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓狐血,卻偏偏與公主長得像淀歇,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子匈织,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容