swift的值型別與inout
1、什麼是值型別
值型別與引用型別相對,值型別的資料特徵是,每一個記憶體例項都會有一份資料copy。在swift語言中,用struct定義的型別都是值型別,這包括了基本資料型別(Int,String,Double,Float),集合型別(Array,Dictionary,Set)等。值型別在賦值和傳遞的過程中,會表現出copy資料的性質。
struct Point {
var x = 0
var y = 0
}
var point1 = Point()
var point2 = point1
我們定義兩個值型別的變數point1、point2,當我們使用point1對point2進行賦值的時候,理論上編譯器會建立point2物件,並將point1的資料進行一次copy賦值給point2。如果我們修改了point2的內容,我們會發現point1的內容並沒有發生變化。
point2.x = 1
print(point2.x) // 1
print(point1.x) // 0, 對point2的修改不會影響point1的內容
2、值型別的優缺點
執行緒的目標是提升程式的執行效率,但是由於資料線上程之間的共享所帶來的複雜度,大大的削弱了這種效能的提升帶來的好處。甚至在複雜的執行緒鎖機制下,在某些情況下執行緒帶來了效能的提升變得微乎其微。值型別的設計可以有效的降低程式設計問題的複雜度,編譯器保證值型別的資料擁有者都持有一份資料的私有copy,這種資料的私有性可以讓資料的的持有者安全的修改自己的資料,而不需要擔心其它執行緒可能會修改這些資料而被迫採用使用執行緒鎖。
因為值型別資料有機會直接在棧空間分配記憶體,所以可以減少堆上記憶體分配和回收的次數,這對於要在堆上建立大量的小物件而言,值型別表現出了特有的優勢。但是理論上,值型別在賦值和傳遞的過程中總是需要進行copy會帶來一定效能的影響,swift使用了很多優化機制,來減輕copy帶了的效能影響。
編譯器可以將copy操作延時到不得不進行copy的時候再進行操作(比如常常被提到的“寫時拷貝”),更進一步來說,當一個結構體不要求在記憶體空間中連續存放的話,那麼當發生“寫時copy”的時候,編譯器則完全只處理髒資料的copy,而繼續共享相同內容的資料。
- swift語言的設計者重視值型別,將90%的內容都設計為值型別,而且平等的強調了let與var(在很多語言中預設宣告的都是變數,常量需要用特殊的關鍵字來進行修飾)。swift語言中的let關鍵字與值型別配合可以讓不變性在語義上更加完整。
let array = [1,2,3,4,5]
array.append(6) // error!!!!!!!
如果array是一個引用型別,let的宣告只能限制array不可以再指向其它內容,但let無法限制我們在array所指向的物件中新增內容(既在資料中新增內容)。但此時array是一個值型別,swift編譯器保證用let修飾過的值型別不可變,從而將不變性的語義更加完整。
3、inout
我們現在已經知道,值型別在傳遞的過程中會進行資料的copy,那麼顯而易見的是下面改變x的值是不會成功的
var x = 10
func changeX(x: Int) {
x + = 10
}
changeX(x)
print(x) // 10 x的值不會發生改變
如果我們希望x的值可以被改變,那麼我們必須使用引用的方式來傳遞x。這時候我們就需要使用inout,當我們使用inout的時候,編譯器不論當前struct的存放狀態如何,都一定會把結構體放入一個連續的記憶體空間中,並將地址作為引數進行傳遞。
var x = 10
func changeX(x: inOut Int) { // swift3.0改變了inOut修飾符的位置
x + = 10
}
changeX(x)
print(x) // 20 x的值發生了改變
相關文章
- Swift-Optional Binding引發的值型別與引用型別的思考Swift型別
- Swift Talk:理解值型別Swift型別
- swift值型別的執行緒安全Swift型別執行緒
- 值型別與引用型別的區別型別
- 理解 Swift 中的元型別:.Type 與 .selfSwift型別
- JavaScript - 基本型別與引用型別值JavaScript型別
- Go: 指標方法與值方法<->指標型別與值型別Go指標型別
- Swift 型別擦除Swift型別
- [譯]Swift 中的型別擦除Swift型別
- Swift 可選型別Swift型別
- TreeSet的null值與元素型別的約束Null型別
- 值型別和引用型別型別
- C#學習筆記之值型別與引用型別C#筆記型別
- 33 個 JavaScript 核心概念系列(二): 值型別與引用型別JavaScript型別
- Swift中Result型別的強大功能Swift型別
- 從 Swift 中的序列到型別擦除Swift型別
- 詳解MySQL儲存過程引數有三種型別(in、out、inout)MySql儲存過程型別
- c#:值型別&引用型別C#型別
- JavaScript值型別和引用型別JavaScript型別
- 多型中的返回值型別多型型別
- 從賦值看基本型別和引用型別的區別賦值型別
- 淺析number型別的值型別
- TypeScript 數值型別TypeScript型別
- Python數值型別Python型別
- javascript原始值和引用值型別及區別JavaScript型別
- swift基本資料型別使用-字典使用Swift資料型別
- [JS高程] 特殊的原始值型別JS型別
- 判斷值的資料型別資料型別
- 區別值型別資料和引用型別資料型別
- Golang的值型別和引用型別的範圍、儲存區域、區別Golang型別
- Golang 中函式作為值與型別(轉載)Golang函式型別
- Kotlin 資料型別詳解:數字、字元、布林值與型別轉換指南Kotlin資料型別字元
- golang中 值型別,指標,引用的區別Golang型別指標
- Golang 基礎值速學之十九(函式作為值與型別)Golang函式型別
- js基本語法之 值型別(資料型別)(變數型別)JS資料型別變數
- JavaScript - 變數、值、型別JavaScript變數型別
- CSS 顏色值型別CSS型別
- 把一個任意型別的值轉換為布林型別型別
- 最新 Swift5 常見資料型別Swift資料型別