「这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战」。
1.2 swift_allocObject 源码分析
void *swift::swift_slowAlloc(size_t size, size_t alignMask) {
void *p;
//这个检查也强制“默认”对齐使用AlignedAlloc。 if (alignMask <= MALLOC_ALIGN_MASK) {
#if defined(__APPLE__)
p = malloc_zone_malloc(DEFAULT_ZONE(), size);
#else
p = malloc(size);// 堆中创建size大小的内存空间,用于存储实例变量
#endif
} else {
size_t alignment = (alignMask == ~(size_t(0)))
? _swift_MinAllocationAlignment
: alignMask + 1;
p = AlignedAlloc(size, alignment);
}
if (!p) swift::crash("Could not allocate memory.");
return p;
}
- 进入
swift_slowAlloc函数,其内部主要是通过malloc_zone_malloc在堆中分配size大小的内存空间,并返回内存地址,主要是用于存储实例变量
1.3 查看HeapObject 并 计算类的大小
// The members of the HeapObject header that are not shared by a
// standard Objective-C instance
#define SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS \
InlineRefCounts refCounts ///引用计数
/// The Swift heap-object header.
/// This must match RefCountedStructTy in IRGen.
struct HeapObject {
/// This is always a valid pointer to a metadata object.
HeapMetadata const *metadata;/// 元数据
SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS; ///引用计数
metadata:是 HeapMetedata类型refCounts: 引用计数
【总结】
- Swift中实例对象,默认的比OC中多了一个refCounted引用计数大小,默认属性占16字节 : metadata(struct)8字节和refCounts(class)8字节
- OC中实例对象的本质是结构体,是以objc_object为模板继承的,其中有一个isa指针,占8字节
1.4【验证+拓展】
//验证
class HJPerson {
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print(class_getInstanceSize(HJPerson.self))
}
}
打印 : 16
//拓展
class HJPerson {
var age : Int = 20
var name : String = "HJ"
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print(class_getInstanceSize(HJPerson.self))
}
}
打印 : 40
验证的确一个空类的大小为16;那么为啥第二个是40呢?
我们通过打印Int 和 String 内存大小来验证
//********* Int底层定义 *********
@frozen public struct Int : FixedWidthInteger, SignedInteger {...}
//String底层定义
@frozen public struct String {...}
//验证
print(MemoryLayout<Int>.stride)
print(MemoryLayout<String>.stride)
打印
8
16
- 从打印的结果中可以看出,Int类型占8字节,String类型占16字节,这点与OC中是有所区别的 ,以后再进行详细讲解吧。
- 所以这也解释了为什么HJPerson的内存大小等于40,即40 = metadata(8字节) +refCount(8字节)+ Int(8字节)+ String(16字节)
二、Swift中类的结构探索
-
在OC中类是从
objc_class模板继承过来的 -
在Swift中,类的结构在底层是
HeapObject,其中有metadata+refCounts
2.1 metadata的底层探索
- 进入HeapMetadata定义,是TargetHeapMetaData类型的别名,接收了一个参数Inprocess
using HeapMetadata = TargetHeapMetaData<Inprocess>;
- 进入TargetHeapMetaData定义,其本质是一个模板类型,其中定义了一些所需的数据结构。这个结构体中没有属性,只有初始化方法,传入了一个MetadataKind类型的参数(该结构体没有,那么只有在父类中了)这里的kind就是传入的Inprocess
//模板类型
template <typename Runtime>
struct TargetHeapMetadata : TargetMetadata<Runtime> {
using HeaderType = TargetHeapMetadataHeader<Runtime>;
TargetHeapMetadata() = default;
//初始化方法
constexpr TargetHeapMetadata(MetadataKind kind)
: TargetMetadata<Runtime>(kind) {}
};