枚举(enum)

枚举的成员类型

相对于OC的枚举来说.Swift中的枚举功用要愈加强壮

OC中枚举值只能是int型.而Swift中的枚举值可所以int,char,String.同一个枚举中的值也可所以不同类型.

枚举的原始指针变量和普通变量的差异值(raw指针变量是什么意思Value)

当咱们给枚举设置了类型后,枚举的成员都有必要是相同类型.咱们也能够用一个默指针变量和指针的差异认值将每个枚举值相关起来指针变量怎样完成对变量的指向.

当设置为String和Int类指针变量是什么意思型时,swift会主动为枚举成员设置原始值

enum T实例化目标的关键字est : String{
case test1 = "test1"
case teswiftkeyst2 = "tesswiftkeyt2"
}
enum Test1 : String{
case test1
case test2
}
print(Test.test1.rawValue)		//t实例化servlet类反常est1
print(Tesswift世界结算体系t1.test1.rawValue)		//test1
enum TestNumber:Int {
case first
case seconde
}
enum TestNumber1:Int {
case first = 0
case sec指针变量和指针的差异onde = 1
}
print(TestNumber.first.rawValue指针变量怎样完成对变量的指向)		//0
print(TestNumber1.指针变量first.rawVa实例化类lue)		//0

枚举的相关值

有时分指针变量会将枚举的成员值跟其他类型的值相关存储在一swift言语起.

enum Time {
case intValue(hour:Int,min:Int,sec:In指针变量是用来存储什么的变量t)
case stringValue(String)
}
var time = Time.intValue(hour: 10, min: 10, sec: 10)
time = .stringV实例化一个类alue("10:20:21")

枚举的内存分配

没有相关值的枚举.有多个case的情况下占用的内存为1个字节.只用来寄存枚举的成员值.而枚举的原始值,经过其他方法获取.swift代码假定只需一个case.不占用内存

enum Test {
case number
case otheSwiftr
}
MemoryLayout<Test>.siz实例化目标的关键字e //1
MemoryLayout<Test>.stride //1
MemoryLayout<Test>.alignment //1
var t = Test.number
//内存散布
//00
t = Test.other
//01
enum Test1 {
case number
}
MemoryLayout<Teswift代码是什么意思st1>.size //0
MemoryLayout<Test1>实例化类.stride //1
MemoryLayout<Test1&实例化目标gt;.alignment //1

存在相关值的枚举.在内存中占用的字节为占用字节最大相关值的字节巨细+1.

究竟的1个字节寄存枚举的成员指针变量赋值值.也能够理解为序号.标明swift世界结算体系当时是哪个case.而前面的字节寄存相关值

enum Test {
case number(Int, Int, Int, Int)
case other
}
MemoryLayout<Test>.siz指针变量是用来存储什么的变量e //33
MemoryLayoutswifter<Test>.sswiftertride //40
MemoryLayout<Te指针变量怎样完成对变量的指向st>.alswifterignment //8
var t = Test.实例化目标的关键字number(1, 2, 3, 4)
//内存散布
//01 00 00 00 00 00 00 00
//02 00 00 00 00 00 00 00
//03 00 00 00 00 00 00 00
//04 00 00 00 00 00 00 00
//00
//00 00 00 00 00 00 00
t = Tswiftlyest.other
//00 00 00 00 00 00 00 00
//00 00 00 00 00 00 00 00
//00 00 00 00 00 00 00 00
//00 00 00 00 00 00 00 00
//01
//00 00 00 00 00 00 00

结构体(struct)swift代码是什么意思

swift中 绝大多数揭穿类型都swift体系是结构体. 枚举和类只占小部分

Bool Int Doub实例化目标le String Array Dictionary等常见类型都是结构体

结构体的初始化器

结构体会主动生成初始化器

struct A{
var a1: Int
var a2: Int
}
var a1 = A(a1: 10, a2: 10)
var a2 = A(a2: 10)指针变量的界说              //Missing argument for parameter 'a1' in call
var a3 = A(a1: 10)              //Missing argument for parameter 'a2' in call
va实例化目标r a4 = A()                    //Missing arguments for param指针变量的界说eters指针变量和普通变量的差异 'a1', 'a2' in call
struct C {
var a:Int = 0
var b:Int = 0
var c:Int = 0
func printValue() {
print(a,b,c)
}
}
var c实例化一个类1 = C(a: 10, b: 10, c: 10)
var c2 = C(a: 10)
var c3 = C(b: 10)
var c4 = C(c: 10)
var c5 = C()
c1.printValue()     //10 10 10
c2.printValue()     //10 0 0
c3.swift世界结算体系printValue()     //0 10 0
c4.printValue()     //0 0 10
c5.printValue()     //0 0 0
struct C1 {
var a:Int
var b:Int
var c:Int
init() {
self.a = 0;
self.b = 0;
self.c = 0;
}
func printValue() {
print(a,b,c)
}
}
var c1 = C1(a: 10, b: 10, c: 10)    //Argument passed to call that takes no arguments
var c2 = C1(a: 10)swift体系                  //Argswiftkeyument passed to call that taswift言语kes no arguments
var c3 = C1(b: 10)                  //Argument passed to cal实例化目标的关键字l that takes no arguments
var c4 = C1(c: 10)                  //Argumen实例化是什么意思t passed to call指针变量是用来存储什么的变量 that takes no arguments
var c5 = C1()
c1.pr实例化servlet类反常intValue()     //10 10 10
c2.pr指针变量和指针的差异intValue()     //10 0 0
c指针变量赋值3.printVswifteralue()     /实例化需求/0 10 0
c4.printValue()     //0 0 10
c5.printValue()     //0 0 0

比照A跟C能够看出.当当咱们没有swift代码声明初始化器的时分.会依据情况主动生成初始化器.

  • 假定结构体声明成员变量时给了初始值,则会生成多个初始化器.
  • 假定成员变量没有初始值,则只会主动生成一个需要给悉数成员赋值的初始化器

结论:结构体初始化结束时,有必要保证悉数的成员变量有值

实例化需求比C跟C1两个根本swift怎样读相同的结构体.能够看到.假定界说了初始化器,则其他的初指针变量是用来存储什么的变量始化器都不会主动生成.

结构体的内存实例化布局

struct C指针变量 {
var a:Int = 0
var b:Int = 0
var c:Int = 0
func printValue() {
print(实例化a,b,c)
}
}
var c1 = C(a: 10, b: 10, c: 10)
print(MemoryLayout.size(ofValue: c1))//24

检查汇编代码发现,结构体实例化时调用了structswifter.C.init方法来进行结构体的实例化指针变量作为函数参数.

->  0x100003848 <+8>:   movl指针变量的界说   $0xa, %eax
0x10000384d <+13>:  movl   %edi, -0x1c(%rbp)
0x100003850 <+16>:  movq   %rax, %rdi
0x100003853 <+19>:  movq   %rsi, -0x28实例化目标的关键字(%rbp)
0x100003857 <+23>指针变量的界说:  movq   %rax, %rsi
0x10000385a <+26>指针变量怎样完成对变量的指向:  movq   %rax, %rdx
0x10000385d <+29>:  callq  0x100003b90               ; struct.C.init(a: Swift.Int, b: Swift.Int, c: Swift.Int) -> struct.C at main.swift:10

结构体C中.界说了3个Int成员变量.各占8个字节.经过MemoryLayou实例化是什么意思t.size(ofValue: c1)得到效果24.所以能够得出结论.结构体的内存巨细为悉数成员变量的总和.那在内存上它是怎样散布的swiftly呢.

这儿咱们经过断点,窥探内存分实例化数组

Swift 枚举,结构体,类

0x100008038 | 0A 00 00 00 00 00 00 00 0A 00 00 00 00 00 00 00 0A 00 00 00 00 00 00 00

发现0x100008038后的接连24个字实例化类节,每八个字节都是十六进制值0000000A,也就是十进制10.阐明结构体的内存是在栈上接连散布的.每n位寄存对应的成员变量值.n=成员变量类型占用字节巨细.

结构体赋值

当咱们把一个现有的结构体变量赋值给另一个结构体变量,而且批改其间一个结构体的某个成员值,会产生什么呢

struct C {
var a:Int = 0
v指针变量ar b:Int = 0
vSwiftar c:Int =指针变量p进行自加运算 0
func pr指针变量p进行自加运算intValue() {
pri指针变量赋值nt(a,b,c)
}
}
var c1 = C(a: 10, b: 10, c: 10)
var c2 = c1
c1.a实例化 = 20
c1.prin实例化servlet类反常tValu指针变量和指针的差异e()	//20 10 10
c2.printValue()	//10 10 10

结论阐明结构体之间的赋值.是深复制.

当一个结构体被赋值给另一个结构体时,会从头拓荒一段接连的内存,swift怎样读再将对应的值放入对应的方位.当结束这一操作后,两个结构体彻底独立.

咱们能够依照上swiftstack面的实例化目标是什么意思方法看看他们的内存散布

c1--0x100008038 | 14 00 00 00 00 00 00 00 0A 00 00 00 00 00 00 00 0A 00 00 00 00 00 00 00
c2--0x100008050 | 0A 00 00 00 00 00 00 00 0A 00 00 00 00 00 00 00 0A 00 00 00 00 00 00 00

能够发现两者的内存散布是正好相差了24个字节.也印证了上面说的,结构体在栈上接连散布.

结构体的写时复制(copy on write)

在swift中,实例化类String, Array, Dictionary等结构体类型,为了不浪费内存,采取了copy on write操作.

即:当上述类型赋值时,假定没有进行写的操作.两个变量都实例化类会指向同一块地址.当进行了写操作时,才会履行实例化目标是什么意思复制操作.

类(class)

类的初始化器

类与结构体长得很类似.可是类生成初始化器的规矩并不同.

classwift怎样读s A {
var a = 0
var b = 0
}
let a = A()
class B {					//Class 'B' has no initializers
var a : Int
var b : Int
}
let b = B()				//'B' cannot be constructed because it has noswift言语 accessible initializers
class C {
varswift代码是什么意思 a : Int
var b : Int
init() {}			//Return from initializer without实例化目标 initializing all stored properties
}
let c = C()
cl指针变量ass D {
var a : Int
var b : Int
init()指针变量p进行自加运算 {
self.a = 0
self.b = 0
}
}
let d = D()
class E {
var a : Int
var b : Int
init(a:Int, b:Int) {
self.a = a
self.b = b
}
}
let e = E(a: 10, b: 10)

经过上面的比如能够发现.假定在声明类的时分,有以下几种或许

  • 类的成员变量添加了初始值.则会主动生成无参的初始化器.
  • 类成员变量没有初始值,声明无参初始化器,需要在初始化器中为成员变量赋值
  • 手动声实例化是什么意思明带参数的初始化器

类的内存散布

下面经过汇编,能够看到在初始化类时,调用了__allocating_init.

class A {
var a = 10
var b = 10
}
let a = A()
->  0x100003实例化目标有几种方式251 <+17>: movq   %rcx, %rdi
0x100003254 <+20>: movq   %rsi, -0x18(%r实例化servlet类反常bp)
0x100003258 <+24>:实例化servlet类反常 callq  0x100003指针变量作为函数参数2a0               ; t实例化一个类ype metadata accessor for struct.A at <compiler-generated>
0x10000325d <+29>: movq   %raxswift代码是什么意思, %r13
0x100003260 <+32>: movq   %rdx, -0x20(%rbp)
0x100003264 <+36>: callq  0x1000036e0               ; struct.A.__allocating_init() -> struct.A at main.swift:11

继续往下盯梢,_allocating_init->_swift代码swift_allocObject -> swift_slow_alloc -> malloc

会发现究竟调用了m实例化需求alloc方法.阐明在初实例化目标的关键字始化类实例政策的过程中.会在堆空间拓荒一段新的内存,用来寄存实例政策的内容.咱们来看看堆实例化数组空间寄存了什么

a | 0x10057fc20 28 82 00 00 01实例化目标是什么意思 00 00 00
03 00 00 00 02 00 00 00
0A实例化类 00 00 00 00 00 00 00
0A 00 00 00 00 00 00 00

经过检查内存散布.发现有两个0A的值.正好就是a和b的值.而前实例化目标有几种方式面的16位.分别寄存了政策的引证计数以实例化servlet类反常及类型信息

类的赋值

class A {
var a = 10
varswift代码 b = 10
func print指针变量是用来存储什么的变量Vaswift体系lue() {
print(a,b)
}
}
let a = A()
let b = a
b.a = 20
a.printValue()	/swifter/20 10
b.printValu指针变量e()	//20 10

与结构体不同,类赋值时,是浅复制.仅仅将堆地址复制了一份.批改其间一个实例政策变量的值,都会引起另一个值的改变

实例化一个类和结构体的不同

类型上:

  • 结构体:值类型 赋值给另一个参数.等于值传递.会复制多一份内存.且两部分内存彻底独立.深复制
  • 类:引证类型 赋值不时引swift代码是什么意思用传递,只传递了指针 浅复制

在内存中:

  • 结构体:栈上接连的N个字节.N = 结构体的size,结构swift代码体或许存在在栈或大局区(数据段)
  • 类:栈上寄存指针变量.指针指向堆中实际类政策的地址,类一向存在堆区.可是指向它的指针有或许存在栈或大局区指针变量和指针的差异(数据段)

实例化是什么意思始化:

  • 结构体:只调用iswift言语nit方法

  • 类: _allocating_init ->指针变量作为函数参数 _swift_allo指针变量占几个字节cObject指针变量的界说> swift_slow_al实例化数组loc -> malloc