pushq %rbp
//很明显,往下读pushq movl 参数入栈和传递
movq %rsp, %rbp
pushq %r13
pushq %rax
movl $0x28, %esi
movl $0x7, %edx
movl %r13, %rdi
callq 0x1000000fd ;symbol stub for: swift_allocObject
//为对象开辟内存空间
movq %rax, %r13
callq 0x1000000ed ;Object.instance.init() -> objc.instance at mian.swift
//调用init初始化
addq $0x8 , %rsp
popq %r13
popq %rbp
retq
//参数出栈,并返回
Swift | ||
---|---|---|
初始化对象所需要参数 | HeapMetadata,requiredSize,AlignmentMask | instanceSize,calloc,initIsa |
相同点 | Size & AlignmentMask | Size & align16 & fastallocCacheMask |
Size大小 | metadata, refCounts 16字节 | ISA,cache,bits,superclass 大于32字节 |
对齐 | 8字节对齐 | 16字节对齐 |
在堆处创建大小空间 | malloc | calloc |
方法存储位置 | metadata() | method_list |
struct{
HeamMeatadata const *metadata;
define SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS InlineRefCounts refCounts
}
很明显,swift 有两个常驻成员1.元类数据 指针8字节 2.引用计数,本质上是一个类 也是指针占8字节
相对于OC类的不同可以看我以前写的文章
有一段注释:The kind .Only valid for non-class metadata; getKind() must be used to get the kind value
Kind是什么?
StoredPointer Kind; 储存指针?
name | value |
---|---|
Class | 0x0 |
Struct | 0x200 |
Enum | 0x201 |
Optional | 0x202 |
ForeignClass | 0x203 |
Opaque | 0x300 |
Tuple | 0x301 |
Function | 0x303 |
Existential | 0x303 |
Metatype | 0x304 |
ObjCClassWrapper | 0x305 |
ExistentialMetatype | 0x306 |
HeapLocalVariable | 0x400 |
HeapGenericLocalVariable | 0x500 |
ErrorObject | 0x51 |
LastEnumerated | 0x7FF |
Metadata::Class ----> TargetMetadata(属性)----> TargetAnyClassMetadata(kind,superclass,cacheData) ---->TargetHeapMeatdata ---->TargetMetadata(kind)
总的来说上面的N重继承为了表达一个东西:
swift_class_t{
void *isa; //isa,kind(unsigned long)
void *superClass
void *cacheData
flags
instanceAddressOffset
instanceSize
instanceAlignMask
reserved
classSize
classAddressOffset
void *description
}
和OC好像,可以看出如果我的Class继承的是NSObject的话,那么kind就是isa
反之,则是普通的swift类,为普通的unsigned lonog kind
var name: String = "" {
willSet{ //新值存储之前调用
print("willSet newValue\(newValue)")
}
didSet{ //新值存储后,value就变成了old
print("didSet oldValue\(oldValue)")
}
}
如何证明的确调用了这两个方法呢?查看sil代码
%0 :String, let , name "value", argno 1
%1 :Test, let, name "self", argno 2
%4 = ret_element_addr %1 :$Test, #Test.name
参数传递
%5 = begin_access [read] [dynamic] %4 : $*Sting
参数出栈,相当于%5=(String *)&name
%6 = load %5 : $*String
存储到%6 oldValue = %5
%10 = fun_ref : convention(method)
%11 = apply %10(%0,%1)
传递两个参数(%0,%1)
retain_value %0 :String
retain(newValue)
%13 = ref_element_addr %1:@convention(method)
%13 = &%1
%14 = begin_access [modify] [dynamic] %13: $*String
%15 = load %14
%15 = *%14
store %0 to %14 :$*String
newValue = %0
release_value %15
%15 = nil
end_access %14
%19 = func_ref
%20 = %19(%6,%1)
&oldValue =name
答案是不会,在类的初始化的内存结构中
didSet{
print(self.age)
}
init(){
age = 18
}
init不会调用属性观察者,如果调用了,那么访问的是上面内存空间的空白处,也就是所谓的野指针,但是这在Swift中是不被允许的,所以print无法打印self.age
1.定义的储存属性 var name: Sting = "xx"
2.类继承的存储属性 class T1:T2{override var name:String}
3.继承计算属性 var age:Int{get{age} set{self.age = newValue }} override var age: Int
从中可以看出,override是比set get 方法优先的
struct Test{
var age: Int
var name: String
}
.sil struct{
@hasStorage var age: Int {get set}
@hasStroage var name: String {get set}
inint(age:Int , name:String)
}
假如结构体初始化变量已经有了初始值,那么就不会调用init方法
%1 = alloc_stack $Test, let , name "self"
%1=struct.self
%2 = interger_literal $Builtin.Int64, 10
%2 = 10
%4 = struct_element_addr %1: $*Test, #age
%4 = &struct->age
store %3 to %4 $*Int
%4 = (Int *)%3
return %10 : Test
值类型中,尽量避免包含有引用类型,在传递过程中还是用strong_retain 引用计数来管理的
参数通常是let属性,如果要修改let 则需要添加inout关键字,对于方法来说需要添加mutating
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。