init()
函数
在 Array
里
public init() {
_buffer = _Buffer()
}
以Buffer
是 _ContiguousArrayBuffer
为例。
即初始化了一个_ContiguousArrayBuffer
。
在_ContiguousArrayBuffer
里
/// Create an empty buffer.
@inlinable
internal init() {
_storage = _emptyArrayStorage
}
其中 _emptyArrayStorage
是一个__EmptyArrayStorage
类的实例,对于所有的空数组,返回的都是同一个地址。
/// The empty array prototype. We use the same object for all empty
/// `[Native]Array`s.
@inlinable
internal var _emptyArrayStorage : __EmptyArrayStorage {
return Builtin.bridgeFromRawPointer(
Builtin.addressof(&_swiftEmptyArrayStorage))
}
_swiftEmptyArrayStorage
定义如下:
SWIFT_RUNTIME_STDLIB_API
swift::_SwiftEmptyArrayStorage swift::_swiftEmptyArrayStorage = {
// HeapObject header;
{
&swift::CLASS_METADATA_SYM(s19__EmptyArrayStorage), // isa pointer
},
// _SwiftArrayBodyStorage body;
{
0, // int count;
1 // unsigned int _capacityAndFlags; 1 means elementTypeIsBridgedVerbatim
}
};
init(repeatedValue, count)
方法
根据元素类型,初始化_ContiguousArrayStorage
类,并在堆上空间,类的尾部分配若干内存,用于存储元素。
然后使用传入的value
,从头初始化内存。
public init(repeating repeatedValue: Element, count: Int) {
var p: UnsafeMutablePointer
(self, p) = Array._allocateUninitialized(count)
for _ in 0..
internal static func _allocateUninitialized(
_ count: Int
) -> (Array, UnsafeMutablePointer) {
let result = Array(_uninitializedCount: count)
return (result, result._buffer.firstElementAddress)
}
init(_ s: S)
方法
public init(_ s: S) where S.Element == Element {
self = Array(
_buffer: _Buffer(
_buffer: s._copyToContiguousArray()._buffer,
shiftedToStartIndex: 0))
}
把Sequence
转为ContiguousArray
,然后再转为Array
。
internal func _copySequenceToContiguousArray<
S : Sequence
>(_ source: S) -> ContiguousArray {
let initialCapacity = source.underestimatedCount
var builder =
_UnsafePartiallyInitializedContiguousArrayBuffer(
initialCapacity: initialCapacity)
var iterator = source.makeIterator()
// FIXME(performance): use _copyContents(initializing:).
// Add elements up to the initial capacity without checking for regrowth.
for _ in 0..
其中用到了Sequence
的iterator
。
在遍历过程中,可能会存在内存不够,需要重新分配内存。
/// Add an element to the buffer, reallocating if necessary.
@inlinable
@inline(__always) // For performance reasons.
internal mutating func add(_ element: Element) {
if remainingCapacity == 0 {
// Reallocate.
let newCapacity = max(_growArrayCapacity(result.capacity), 1)
var newResult = _ContiguousArrayBuffer(
_uninitializedCount: newCapacity, minimumCapacity: 0)
p = newResult.firstElementAddress + result.capacity
remainingCapacity = newResult.capacity - result.capacity
if !result.isEmpty {
// This check prevents a data race writting to _swiftEmptyArrayStorage
// Since count is always 0 there, this code does nothing anyway
newResult.firstElementAddress.moveInitialize(
from: result.firstElementAddress, count: result.capacity)
result.count = 0
}
(result, newResult) = (newResult, result)
}
addWithExistingCapacity(element)
}
分配内存时,大小是指数级增长。
@inlinable
internal func _growArrayCapacity(_ capacity: Int) -> Int {
return capacity * 2
}