Dictionary uses two storage schemes: native storage and Cocoa storage.
只看 native storage 的,也就是和 OC 无关的。
类图

内存分布

分配内存的地方:
static internal func allocate(
scale: Int8,
age: Int32?,
seed: Int?
) -> _DictionaryStorage {
// The entry count must be representable by an Int value; hence the scale's
// peculiar upper bound.
_internalInvariant(scale >= 0 && scale < Int.bitWidth - 1)
let bucketCount = (1 as Int) &<< scale
let wordCount = _UnsafeBitset.wordCount(forCapacity: bucketCount)
let storage = Builtin.allocWithTailElems_3(
_DictionaryStorage<Key, Value>.self,
wordCount._builtinWordValue, _HashTable.Word.self,
bucketCount._builtinWordValue, Key.self,
bucketCount._builtinWordValue, Value.self)
let metadataAddr = Builtin.projectTailElems(storage, _HashTable.Word.self)
let keysAddr = Builtin.getTailAddr_Word(
metadataAddr, wordCount._builtinWordValue, _HashTable.Word.self,
Key.self)
let valuesAddr = Builtin.getTailAddr_Word(
keysAddr, bucketCount._builtinWordValue, Key.self,
Value.self)
storage._count = 0
storage._capacity = _HashTable.capacity(forScale: scale)
storage._scale = scale
storage._reservedScale = 0
storage._extra = 0
if let age = age {
storage._age = age
} else {
// The default mutation count is simply a scrambled version of the storage
// address.
storage._age = Int32(
truncatingIfNeeded: ObjectIdentifier(storage).hashValue)
}
storage._seed = seed ?? _HashTable.hashSeed(for: storage, scale: scale)
storage._rawKeys = UnsafeMutableRawPointer(keysAddr)
storage._rawValues = UnsafeMutableRawPointer(valuesAddr)
// Initialize hash table metadata.
storage._hashTable.clear()
return storage
}
和 Set 区别
区别仅仅在于storage 尾部有两个数组,一个存储key ,一个存储value 。
进行各种操作时,要同时操作key 和value 。
@inlinable // FIXME(inline-always) was usableFromInline
@inline(__always)
internal func uncheckedInitialize(
at bucket: Bucket,
toKey key: __owned Key,
value: __owned Value) {
defer { _fixLifetime(self) }
_internalInvariant(hashTable.isValid(bucket))
(_keys + bucket.offset).initialize(to: key)
(_values + bucket.offset).initialize(to: value)
}
|
请发表评论