Swift 中 MemoryLayout.size 中数组的大小
Posted
技术标签:
【中文标题】Swift 中 MemoryLayout.size 中数组的大小【英文标题】:Size of arrays in MemoryLayout.size in Swift 【发布时间】:2020-06-10 12:11:48 【问题描述】:对不起,如果问题可能重复,我在这里找不到,也无法使用谷歌。
我是不安全的 Swift 新手,我想知道为什么布尔数组的大小(例如 10 个字节)仍然是 8 个字节?
如果我不能说出我的意思,我想知道你是否可以看看这段代码:
var boolArray = [Bool]()
for _ in 1...10
boolArray.append(true)
print(MemoryLayout.size(ofValue: boolArray))
我不明白为什么它打印 8 而数组有 10 个至少包含 10 个字节的布尔值。
【问题讨论】:
无关但有用:您可以将数组生成缩短为Array(repeating: true, count: 10)
或者如果您正在处理类并想要 10 个不同的对象:(1...10).map _ in YourClass()
@LeoDabus 你是最好的一种权利 - 技术上正确
@ParsaNoori 从技术上讲,您甚至不能在现代 CPU 上加载比缓存行少的任何东西。但是您仍然可以访问成分。虽然您不能单独加载单个位,但您可以加载整个字节,屏蔽除您要查找的位之外的所有位,然后读取它。
@ParsaNoori 由于每个字节有 8 位,您可以使用索引的最后 3 位以外的所有位来选择要查看的字节,并使用最后 3 位来编码你感兴趣的位。例如,如果您想要索引 59 处的Bool
(二进制中的0b111011
),则查看第 7 个字节(0b111
)。假设那个字节的值是0b11111111
(全是“真”)。我们关心位 3 (0b011
),所以我们通过与掩码 0b00000100
进行与运算来掩码 0b1111111
。结果是0b00000100
,表示设置了第3位。
@ParsaNoori 如果该字节的值为0b11111011
,在用0b00000100
屏蔽后,我们将得到0x00000000
,这意味着第3 位已关闭。
【参考方案1】:
这是因为 Array
本身并不真正存储任何东西 - 在内部,它们持有对堆分配内存的引用,它真正存储数据。
这样做的原因之一是优化 - 它允许使用写时复制机制。 Array
是 struct
,因此它是一个值类型。但是,不需要每次复制Array
时都复制它所保存的数据——相反,多个Arrays
可以指向同一个内存区域,只要它们不修改即可。
【讨论】:
有理由猜测代表“Array
容器”的数据结构是 8 个字节长。这是一个只对语言设计者感兴趣的不透明结构。
@MikeRobinson 相反,它的内部工作令人着迷,并且可能会引起许多从未接触过语言设计的人(包括我自己)的极大兴趣。【参考方案2】:
因为函数大小的结果不包括任何动态分配或离线存储。见https://developer.apple.com/documentation/swift/memorylayout/2486283-size
【讨论】:
以上是关于Swift 中 MemoryLayout.size 中数组的大小的主要内容,如果未能解决你的问题,请参考以下文章
我可以在 Swift 3 项目中使用 Swift 2.3 框架吗?
将 Swift 3 升级到 4,目标 c 中不再有 swift 扩展