sizeof
在C语言中,可能会经常与sizeof打交道,用来计算数据占用内存大小。在C中sizeof即可以作用于类型也可以作用于某个实际的变量,并返回其在内存中的尺寸size_t。
在Swift 3以前,也有sizeof,不过与C中的运算符不同,它经过了一层包装,变成了一个只接受类型的方法,而接受具体值的则为另一个方法: sizeofValue
func sizeof<T>(_: T.Type) -> Int
func sizeofValue<T>(_: T) -> Int
不过sizeofValue接受的虽然是具体值,但是返回的是这个值的实际大小,而不是其内容的大小。所以与C中用sizeof拿来计算数组内容在内存中占据的尺寸不一样:
// C
char bytes[] = {1, 2, 3};
sizeof(bytes); // 3
int bytes[] = {1, 2, 3};
sizeof(bytes); // 12
// Swift
let bytes = [1, 2, 3]
sizeofValue(bytes) // 8: 64位系统一个引用的长度
MemoryLayout
在Swift 3中sizeof和sizeofValue相关的被另一个新的枚举所替代,那就是MemoryLayout。
基本使用方法
let a = 10
MemoryLayout<Int>.size // 8
MemoryLayout.size(ofValue: a) // 8
属性方法介绍
MemoryLayout有3个非常有用的属性及3个对应的Value方法,返回值都为Int类型。
size
实例使用size(ofValue: T)
T占用连续内存的大小,单位是字节。类型的大小不包括任何动态分配或不合适的存储,当T是类类型时,MemoryLayout
stride
实例使用stride(ofValue: T)
当存储在连续存储器或Array
示例:
这是一个数组,里面有四个T类型元素,每个T元素的大小为size个字节,但是因为内存对齐的限制,每个T类型元素实际消耗的内存空间为stride个字节,stride - size个字节则为每个元素因为内存对齐而浪费的内存空间。
alignment
实例使用alignment(ofValue: T)
T的默认内存对齐方式,单位为字节。许多计算机系统对基本数据类型的合法地址做出了一些限制,要求某种数据类型对象的地址必须是某个值K(通常是 2、4或者8)的倍数。这种对齐限制简化了形成处理器和内存系统之间接口的硬件设计。对齐原则是任何K字节的基本对象的地址必须是K的倍数。
MemoryLayout.alignment就代表着数据类型T的内存对齐原则。而且在64位系统下,最大的内存对齐原则是8字节。
基本数据类型的MemoryLayout
// 值类型
MemoryLayout<Int>.size // 8
MemoryLayout<Int>.stride // 8
MemoryLayout<Int>.alignment // 8
MemoryLayout<String>.size // 24
MemoryLayout<String>.stride // 24
MemoryLayout<String>.alignment // 8
// 引用类型 T
MemoryLayout<T>.size // 8
MemoryLayout<T>.stride // 8
MemoryLayout<T>.alignment // 8
// 指针类型
MemoryLayout<unsafeMutablePointer<T>>.size // 8
MemoryLayout<unsafeMutablePointer<T>>.stride // 8
MemoryLayout<unsafeMutablePointer<T>>.alignment // 8
MemoryLayout<unsafeMutableBufferPointer<T>>.size // 16
MemoryLayout<unsafeMutableBufferPointer<T>>.stride // 16
MemoryLayout<unsafeMutableBufferPointer<T>>.alignment // 16
注意
以上所有都在64位系统中得到