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

淺析Swift中struct與class的區(qū)別(匯編角度底層分析)

 更新時間:2020年03月05日 15:24:22   作者:國孩  
這篇文章主要介紹了Swift中struct與class的區(qū)別 ,本文從匯編角度分析struct與class的區(qū)別,通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

概述

相對Objective-C, Swift使用結(jié)構(gòu)體Struct的比例大大增加了,其中Int, Bool,以及String,Array等底層全部使用Struct來定義!在Swift中結(jié)構(gòu)體不僅可以定義成員變量(屬性),還可以定義成員方法,和類比較相似,都是具有定義和使用屬性,方法以及初始化器等面向?qū)ο筇匦?但是結(jié)構(gòu)體是不具有繼承性,不具備運行時強制類型轉(zhuǎn)換的以及引用計數(shù)等能力的!

下面來從匯編角度分析struct與class的區(qū)別!

基本知識

1、結(jié)構(gòu)體

自動初始化器

在63行的調(diào)用中可以傳入所有的成員值,用以初始化所有成員(存儲屬性, Stored Property)

在Struct Date定義中,并沒有出現(xiàn)init初始化方法,但是發(fā)現(xiàn)Date會自動出現(xiàn)填入成員值的初始化方法

結(jié)論所有結(jié)構(gòu)體都會有一個編譯器自動生成的初始化器(initializer,構(gòu)造器,構(gòu)造方法),編譯器會根據(jù)情況,可能會為結(jié)構(gòu)體生成多個初始化器,但是宗旨是:保證所有成員都有初始值

舉例1

下面四個初始化器,第一個初始化器之后保證了x,y都有值,滿足了上面說的保證所有成員都有初始值

p1,p2,p3都不能操作成功,因為不能保證全部成員值都有值

通過上面的舉例,編譯器主動生成了一個初始化器,用于接受成員值x,y的初始化器,其他不會主動生成

舉例2

下面四個初始化器,第一個第二個p0,p1保證了x,y都有值,因為x定義的時候賦值為0了,保證了成員值都有初始化值

p2,p3都不能操作成功,因為不能保證全部成員值都有值

通過舉例2,編譯器主動生成了兩個初始化器,用于接受x,y以及單獨接受y即可,其他的初始化器不會生成

舉例3

下面成員值在定義的時候就已經(jīng)給定了初始化值,已經(jīng)保證了所有成員值肯定會有初始化值

所以四個初始化器都可以,編譯器會自動生成四個初始化器

舉例4

下面代碼能編譯通過嘛?

struct Point {
 var x: Int?
 var y: Int?
}
var p0 = Point(x: 0, y: 10)
var p1 = Point(y: 0)
var p2 = Point(x: 0)
var p3 = Point()

定義var x: Int? 相當于將nil 賦值給x,所以上面四個都是可以編譯通過的 可選項都有個默認值nil

自定義初始化器

一旦在定義結(jié)構(gòu)體的時候自定義好了初始化器,編譯器就不會再幫它自動生成其他初始化器

舉例1

struct Point {
 var x: Int = 0
 var y: Int = 0
 init(x: Int, y: Int) {
 self.x = x
 self.y = y
 }
}
var p0 = Point(x: 0, y: 10)
var p1 = Point(y: 0)
var p2 = Point(x: 0)
var p3 = Point()

在定義成員值時并賦值了初始值,也自定義初始化器,所以編譯器就不會自動生成其他初始化器

看下這兩種初始化有何區(qū)別?

func testStruct() {
 struct Point {
 var x: Int = 0
 var y: Int = 0
 }
 var _ = Point()
}
testStruct()
func testStruct() {
 struct Point {
 var x: Int
 var y: Int
 init() {
  x = 0
  y = 0
 }
 }
 var _ = Point()
}
testStruct()

通過匯編來查看是否有區(qū)別,兩個一模一樣,都是下面

TestSwift`init() in Point #1 in testStruct():
-> 0x100001940 <+0>: pushq %rbp
 0x100001941 <+1>: movq %rsp, %rbp
 0x100001944 <+4>: xorps %xmm0, %xmm0
 0x100001947 <+7>: movaps %xmm0, -0x10(%rbp)
 0x10000194b <+11>: movq $0x0, -0x10(%rbp)
 0x100001953 <+19>: movq $0x0, -0x8(%rbp)
 0x10000195b <+27>: xorl %eax, %eax
 0x10000195d <+29>: movl %eax, %ecx
 0x10000195f <+31>: movq %rcx, %rax
 0x100001962 <+34>: movq %rcx, %rdx
 0x100001965 <+37>: popq %rbp
 0x100001966 <+38>: retq

內(nèi)存結(jié)構(gòu)

看一下下面一個結(jié)構(gòu)體的內(nèi)存結(jié)構(gòu)

根據(jù)內(nèi)存地址查看

從上面的存儲可看到,三個屬性的存儲地址是相鄰的!!!

也可以通過封裝的Mems內(nèi)存類來直接查詢

2、類

類的定義和結(jié)構(gòu)體類似, 但是編譯器并沒有為類自動生成可以傳入成員值的初始化器

上面class定義,知編譯器不會自動生成可以傳入成員值的初始化器,因為定義的x,y都具有初始化值,xcode還會自動的生成無參的初始化值,如果x,y沒有初始化值,連無參的初始化器都不會調(diào)用成功!

上面如果改成struct修飾,就不會有任何的錯誤

結(jié)論:

如果類的所有成員都在定義的時候制定了初始值,編譯器會為類生成無參的初始化器

區(qū)別

1. 結(jié)構(gòu)體是值類型(枚舉也是值類型), 類是引用類型(指針類型)

class Size {
 var width = 1
 var height = 2
}
struct Point {
 var x = 3
 var y = 4
}
func test() {
 var size = Size()
 var point = Point()
}

對于上面的代碼,point為值類型,如果值類型在函數(shù)里面定義,就放在??臻g,point里面有x,y共有16個字節(jié),假設起始地址為0x10000,而Size對象是引用類型,size指針變量存放在??臻g中,存放的是地址(指針類型占用8個字節(jié)),地址指向的為堆空間,堆空間的大小為32個字節(jié),內(nèi)存結(jié)構(gòu)大致如

而size對象內(nèi)存則放在堆空間,結(jié)構(gòu)結(jié)構(gòu)如下

進行驗證(如果匯編里面沒有出現(xiàn)alloc,malloc等詞,基本就不是堆空間)

發(fā)現(xiàn)size指針變量和point變量地址挨著很近!!!

進一步,我們想觀看size指針變量指向的堆空間的內(nèi)容和指針地址,通過Mems工具類查看

對于上面的補充

對于類創(chuàng)建的對象都是是堆空間,只是類對象的指針變量可能會在不同的地方,如上面size是在函數(shù)里面,size指針變量放在棧里面,但是Size對象就是堆空間,不存在其他的,如果創(chuàng)建size對象在函數(shù)外創(chuàng)建,則size指針變量就放在了全局區(qū)里面

拓展

值類型: 值類型賦值給var,let或者給函數(shù)傳參, 是直接將所有內(nèi)容拷貝一份,類似于對文件進行copy,paste操作,產(chǎn)生了新的文件副本,屬于深拷貝(deep copy)

匯編指令小技巧

引用類型: 引用賦值給var,let或者給函數(shù)傳參, 是將內(nèi)存地址拷貝一份,類似于制作一個文件的替身(快捷方式、鏈接)指向的是同一個文件,屬于淺拷貝(shallow copy)

上面可看出,s1, s2 都指向同一內(nèi)存,當更改s2的值時,s1也會更改掉,此為淺拷貝的應用!!!

總結(jié)

到此這篇關(guān)于Swift--struct與class的區(qū)別(匯編角度底層分析)的文章就介紹到這了,更多相關(guān)swift struct與class內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Swift類型創(chuàng)建之自定義一個類型詳解

    Swift類型創(chuàng)建之自定義一個類型詳解

    這篇文章主要介紹了Swift類型創(chuàng)建之自定義一個類型詳解,本文講解了自定義原型、實現(xiàn)默認值、支持基本布爾型初始化、支持Bool類型判斷、支持兼容各們各派的類型、完善OCBool的布爾基因體系等內(nèi)容,需要的朋友可以參考下
    2015-05-05
  • 淺談Swift派發(fā)機制

    淺談Swift派發(fā)機制

    派發(fā)目的是讓 CPU 知道被調(diào)用的函數(shù)在哪里。Swift 語言是支持編譯型語言的直接派發(fā),函數(shù)表派發(fā)和消息機制派發(fā)三種派發(fā)方式的,下面分別對這三種派發(fā)方式說明下。
    2021-06-06
  • Swift編程中的一些類型轉(zhuǎn)換方法詳解

    Swift編程中的一些類型轉(zhuǎn)換方法詳解

    這篇文章主要介紹了Swift編程中的一些類型轉(zhuǎn)換方法詳解,是Swift入門學習中的基礎知識,需要的朋友可以參考下
    2015-11-11
  • Swift 4中一些實用的數(shù)組技巧小結(jié)

    Swift 4中一些實用的數(shù)組技巧小結(jié)

    這篇文章主要給大家分享了關(guān)于Swift 4中一些實用的數(shù)組技巧,文中通過示例代碼介紹的介紹的非常詳細,對大家學習或者使用swift具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2018-03-03
  • 純swift實現(xiàn)ipad版簡單美團界面功能

    純swift實現(xiàn)ipad版簡單美團界面功能

    這篇文章主要為大家詳細介紹了純swift實現(xiàn)ipad版簡單美團界面功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • Swift實現(xiàn)無限輪播效果

    Swift實現(xiàn)無限輪播效果

    這篇文章主要為大家詳細介紹了Swift無限輪播效果實現(xiàn)方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • Swift算法實現(xiàn)字符串轉(zhuǎn)數(shù)字的方法示例

    Swift算法實現(xiàn)字符串轉(zhuǎn)數(shù)字的方法示例

    最近學完了swift想著實踐下,就通過一些簡單的算法進行學習研究,下面這篇文章主要介紹了Swift算法實現(xiàn)字符串轉(zhuǎn)數(shù)字的方法,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-03-03
  • swift中defer的實際應用小結(jié)

    swift中defer的實際應用小結(jié)

    這篇文章主要給大家介紹了關(guān)于swift中defer的實際應用的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-01-01
  • swift中的@UIApplicationMain示例詳解

    swift中的@UIApplicationMain示例詳解

    這篇文章主要給大家介紹了關(guān)于swift中@UIApplicationMain的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2017-12-12
  • Swift 基本數(shù)據(jù)類型詳解總結(jié)

    Swift 基本數(shù)據(jù)類型詳解總結(jié)

    在我們使用任何程序語言編程時,需要使用各種數(shù)據(jù)類型來存儲不同的信息。變量的數(shù)據(jù)類型決定了如何將代表這些值的位存儲到計算機的內(nèi)存中。在聲明變量時也可指定它的數(shù)據(jù)類型。所有變量都具有數(shù)據(jù)類型,以決定能夠存儲哪種數(shù)據(jù)
    2021-11-11

最新評論