Swift之結構體

本文首發於個人我的博客html

前言

  • 在 Swift 標準庫中,絕大多數的公開類型都是結構體,而枚舉和類只佔很小一部分
    • 好比Bool、Int、Double、 String、Array、Dictionary等常見類型都是結構體
struct Date {
		var year: Int		
		var month: Int
		var day: Int
	}
 var date = Date(year: 2019, month: 6, day: 23)
複製代碼
  • 全部的結構體都有一個編譯器自動生成的初始化器(initializer,初始化方法、構造器、構造方法)
    • 在最後一行調用的,能夠傳入全部成員值,用以初始化全部成員(存儲屬性,Stored Property)

結構體的初始化器

  • 編譯器會根據狀況,可能會爲結構體生成多個初始化器,宗旨是:保證全部成員都有初始值

eg:git

struct Point{
    var x: Int
    var y: Int
}

var p1 = Point(x: 10, y: 20)
var p2 = Point(y: 20) //報錯 Missing argument for parameter 'x' in call
var p3 = Point(x: 10) //報錯 Missing argument for parameter 'y' in call
var p4 = Point()    //報錯 Missing argument for parameter 'x' in call

複製代碼

若是給定一個初始值github

struct Point{
    var x: Int = 10
    var y: Int
}

var p1 = Point(x: 10, y: 20)
var p2 = Point(y: 20)
var p3 = Point(x: 10) //報錯 Missing argument for parameter 'y' in call
var p4 = Point()    //報錯 Missing argument for parameter 'y' in call
複製代碼

若是x 和 y都有初始值的話,就怎麼都不會報錯了,由於 全部成員都有初始值編程

struct Point{
    var x: Int = 10
    var y: Int = 20
}

var p1 = Point(x: 10, y: 20)
var p2 = Point(y: 20)
var p3 = Point(x: 10) 
var p4 = Point()    
複製代碼

初始值爲nil的話,也能夠編譯經過,好比下面這種bash

struct Point{
    var x: Int?
    var y: Int?
}

var p1 = Point(x: 10, y: 20)
var p2 = Point(y: 20)
var p3 = Point(x: 10) 
var p4 = Point()    
複製代碼

自定義初始化器

  • 一旦在定義結構體時自定義了初始化器,編譯器就不會再幫它自動生成其餘初始化器
struct Point{
    var x: Int = 10
    var y: Int = 20
    init(x: Int, y: Int) {
        self.x = x
        self.y = y
    }
}

var p1 = Point(x: 10, y: 20)
var p2 = Point(y: 20) //報錯 Missing argument for parameter 'x' in call
var p3 = Point(x: 10) //報錯 Missing argument for parameter 'y' in call
var p4 = Point()    //報錯 Missing argument for parameter 'x' in call

複製代碼

窺探初始化器的本質

如下2段代碼徹底等效

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

複製代碼

驗證

func test(){
    struct Point {
        var x: Int = 0
        var y: Int = 0
    }
    let p = Point() //這一行打斷點
    print(p)
}
test()
複製代碼

app

func test(){
    struct Point {
        var x: Int 
        var y: Int 
     	 init() {
           x=0
            y=0
       	}
    }
    let p = Point() //這一行打斷點
    print(p)
}
test()
複製代碼

查看彙編,兩段代碼都是ide

testSwift`init() in Point #1 in test():
->  0x100001d50 <+0>:  pushq  %rbp
    0x100001d51 <+1>:  movq   %rsp, %rbp
    0x100001d54 <+4>:  xorps  %xmm0, %xmm0
    0x100001d57 <+7>:  movaps %xmm0, -0x10(%rbp)
    0x100001d5b <+11>: movq   $0x0, -0x10(%rbp)
    0x100001d63 <+19>: movq   $0x0, -0x8(%rbp)
    0x100001d6b <+27>: xorl   %eax, %eax
    0x100001d6d <+29>: movl   %eax, %ecx
    0x100001d6f <+31>: movq   %rcx, %rax
    0x100001d72 <+34>: movq   %rcx, %rdx
    0x100001d75 <+37>: popq   %rbp
    0x100001d76 <+38>: retq   
複製代碼

這兩段代碼的彙編同樣的,也就是說,這兩段代碼徹底等效工具

結構體的內存結構

struct Point {
        var x: Int = 0
        var y: Int = 0
        var origin: Bool = true

    }
    
 print(MemoryLayout<Point>.size)
 print(MemoryLayout<Point>.stride)
 print(MemoryLayout<Point>.alignment)
複製代碼

打印結果爲ui

17spa

24

8

是由於內存對齊的緣故,17是由於 實際使用的是 8+8+1 = 17 24 是由於,要內存對齊,8*3 = 24

參考資料:

Swift官方源碼

從入門到精通Swift編程

窺探內存細節的小工具

更多資料,歡迎關注我的公衆號,不定時分享各類技術文章。

相關文章
相關標籤/搜索