【四】Swift-指针&内存管理

code_小马swift

目录

一、指针

1.为什么说指针是不安全的

2.指针类型

3.原始指针的使用

4.泛型指针的使用

5.内存绑定


二、内存管理

1.弱引用

2.Unowned

一、指针

1.为什么说指针是不安全的

  • 在创建一个对象的时候,是需要在堆分配内存空间。但是这个内存空间的生命周期是有限的。如果我们使用指针指向这块内存空间,如果当前内存空间的生命周期结束了(引用计数为0,系统回收内存空间),那么我们当前的指针就变成了未定义的行为了(野指针)。
  • :比如我们创建一个count为10的数组,这个时候我们通过指针访问到了index = 11的位置,这个时候就越界了,访问了一个未知的内存空间。
  • ,也是不安全的。

2.指针类型

Swift中指针分为两大类:
typed pointer 指定数据类型的指针;
raw pointer未指定数据类型的指针(原生指针)。

基本上我们接触到的指针类型有以下几中

Swift Object-C 说明 类型
unsafePointer const T * 指针及所指向的内容都不可变 typed pointer
unsafeMutablePointer T * 指针及其所指向的内存内容均可变 typed pointer
unsafeRawPointer const void * 指针指向的内存区域未定 原生指针
unsafeMutableRawPointer void * 同上 原生指针
unsafeBufferPointer typed pointer
unsafeMutableBufferPointer typed pointer
unsafeRawBufferPointer 原生指针
unsafeMutableRawBufferPointer 原生指针

3.原始指针的使用

三个基本概念:内存大小size、步长信息stride、字节对齐alignment

struct YGTeacher {
    var age: Int = 18
    var haveCar: Bool = true
}
//内存大小
print(MemoryLayout.size)
//步长:当前指针需要移动的真实大小
print(MemoryLayout.stride)
//对齐
print(MemoryLayout.alignment)
  • stride(步长):
    如果在内存当中,我要存储几个连续的YGTeacher的实例,那这个步长信息指的是:
    从第一个YGTeacher实例到下一个YGTeacher实例,它所跨越的长度信息。

YGTeacher.jpeg

分析上图打印结果:
Int类型的age占了8个字节
Bool类型的haveCar占了1个字节
所以:YGTeacher这个结构体实际大小size9个字节
由于结构体YGTeacher的对象内存分配字节对齐alignment8个字节
所以不足8字节的Bool类型就要补齐到8个字节(字节对齐原则),
所以当前的步长信息stride16个字节

  • 使用Raw Pointer来存储4个整形的数据:
    这里我们需要选取的是 UnsafeMutableRawPointer
    如下图所示:
存储  :storeBytes
加载  :load
移动  :advanced
输出台信息.png
补充 storeBytes 存储方法

4.泛型指针的使用

  • 如下图:不可变指针-只读,指针和指针指向的地址都不可修改;
    可变类型的指针,指针和指针指向的内容都是可变的。


    可变/不可变类型的指针
  • 指定数据类型的可变指针

分配内存空间allocate、初始化变量initialize、
取消初始设置deinitialize、deallocate释放内存空间


泛型指针的使用
  • 我们可以通过以下方式来初始实话我们的指针
struct YGStruct {
    var age: Int
    var height: Double
}
//分配内存空间,连续存储5个结构体的大小、明确指针内存储的数据类型为 YGStruct
var tPtr = UnsafeMutablePointer.allocate(capacity: 5)
//存储第一个内存地址,赋值
tPtr[0] = YGStruct(age: 15, height: 160.0)
tPtr[1] = YGStruct(age: 21, height: 175.0)
tPtr[2] = YGStruct(age: 25, height: 181.0)
print("①",tPtr[0],"\n1=",tPtr[1],"\n2=",tPtr[2],"\n3=",tPtr[3],"\n4=",tPtr[4]);
//取消初始化释放内存空间
tPtr.deinitialize(count: 5)
tPtr.deallocate()

  • 我们还可通过以下方式初始化指针
struct YGStruct_tow {
    var age = 20
    var height = 1.83
}

let p = UnsafeMutablePointer.allocate(capacity: 2)
p.initialize(to: YGStruct_tow())
p.advanced(by: MemoryLayout.stride).initialize(to: YGStruct_tow(age: 25, height: 1.83))

p.deinitialize(count: 2)
p.deallocate()

记住 initialize、advanceddeinitialize、deallocate要 成对儿 使用。

  • 指针读取Macho中的属性名称
    首先分享一个优化版machOView工具地址(烂苹果)MachOView2.6.1

5.内存绑定

二、内存管理

1.弱引用

2.Unowned

你可能感兴趣的:(【四】Swift-指针&内存管理)