ContiguousArray<Element> is the fastest and simplest of the three(ContiguousArray, Array, ArraySlice) – use this when you need “C array” performance. The elements of a ContiguousArray are always stored contiguously in memory.
The ContiguousArray type is a specialized array that always stores its elements in a contiguous region of memory. This contrasts with Array, which can store its elements in either a contiguous region of memory or an NSArray instance if its Element type is a class or @objc protocol.
If your array’s Element type is a class or @objc protocol and you do not need to bridge the array to NSArray or pass the array to Objective-C APIs, using ContiguousArray may be more efficient and have more predictable performance than Array.
If the array’s Element type is a struct or enumeration, Array and ContiguousArray should have similar efficiency.
/// Initialization from an existing buffer does not have "array.init" /// semantics because the caller may retain an alias to buffer. @inlinable internalinit(_buffer: _Buffer) { self._buffer = _buffer } }
// __ContiguousArrayStorageBase supplies the implementation of the // _NSArrayCore API (and thus, NSArray the API) for our // _ContiguousArrayStorage. We can’t put this implementation // directly on _ContiguousArrayStorage because generic classes can’t // override Objective-C selectors. //
/// Base class of the heap buffer backing arrays. /// /// NOTE: older runtimes called this _ContiguousArrayStorageBase. The /// two must coexist, so it was renamed. The old name must not be used /// in the new runtime. // 大部分方法需要子类实现 @usableFromInline @_fixed_layout internalclass__ContiguousArrayStorageBase: __SwiftNativeNSArrayWithContiguousStorage{ @Usablefrominline finalvar countAndCapacity: _ArrayBody
@inlinable @nonobjc internalinit(_doNotCallMeBase: ()) { _internalInvariantFailure("creating instance of __ContiguousArrayStorageBase") } #if _runtime(_ObjC) internaloverridefuncwithUnsafeBufferOfObjects<R>( _ body: (UnsafeBufferPointer<AnyObject>)throws -> R ) rethrows -> R { iflet result = try _withVerbatimBridgedUnsafeBuffer(body) { return result } _internalInvariantFailure( "Can't use a buffer of non-verbatim-bridged elements as an NSArray") }
/// If the stored type is bridged verbatim, invoke `body` on an /// `UnsafeBufferPointer` to the elements and return the result. /// Otherwise, return `nil`. internalfunc_withVerbatimBridgedUnsafeBuffer<R>( _ body: (UnsafeBufferPointer<AnyObject>)throws -> R ) rethrows -> R? { _internalInvariantFailure( "Concrete subclasses must implement _withVerbatimBridgedUnsafeBuffer") }
/// A type that every element in the array is. @inlinable internalvar staticElementType: Any.Type { _internalInvariantFailure( "Concrete subclasses must implement staticElementType") } @inlinable deinit { _internalInvariant( self !== _emptyArrayStorage, "Deallocating empty array storage?!") } }
/// Make a buffer with uninitialized elements. After using this /// method, you must either initialize the `count` elements at the /// result's `.firstElementAddress` or set the result's `.count` /// to zero. @inlinable internalinit( _uninitializedCount uninitializedCount: Int, minimumCapacity: Int ) { let realMinimumCapacity = Swift.max(uninitializedCount, minimumCapacity) if realMinimumCapacity == 0 { self = _ContiguousArrayBuffer<Element>() } else { // 初始化一个`_ContiguousArrayStorage<Element>`的实例, // 并在后面申请`realMinimumCapacity`大小的连续内存 // 然后更新StorageHeader _storage = Builtin.allocWithTailElems_1( getContiguousArrayStorageType(for: Element.self), realMinimumCapacity._builtinWordValue, Element.self)
/// Initialize the body part of our storage. /// /// - Warning: does not initialize elements @inlinable internalfunc_initStorageHeader(count: Int, capacity: Int) { #if _runtime(_ObjC) let verbatim = _isBridgedVerbatimToObjectiveC(Element.self) #else let verbatim = false #endif // 赋值`_storage`中的`countAndCapacity` // We can initialize by assignment because _ArrayBody is a trivial type, // i.e. contains no references. _storage.countAndCapacity = _ArrayBody( count: count, capacity: capacity, elementTypeIsBridgedVerbatim: verbatim) }
/// An `NSArray` with Swift-native reference counting and contiguous /// storage. /// /// NOTE: older runtimes called this /// _SwiftNativeNSArrayWithContiguousStorage. The two must coexist, so /// it was renamed. The old name must not be used in the new runtime. @_fixed_layout @usableFromInline internalclass__SwiftNativeNSArrayWithContiguousStorage : __SwiftNativeNSArray{ // Provides NSArray inheritance and native refcounting
/// Adds a new element at the end of the array. /// /// Use this method to append a single element to the end of a mutable array. /// /// var numbers = [1, 2, 3, 4, 5] /// numbers.append(100) /// print(numbers) /// // Prints "[1, 2, 3, 4, 5, 100]" /// /// Because arrays increase their allocated capacity using an exponential /// strategy, appending a single element to an array is an O(1) operation /// when averaged over many calls to the `append(_:)` method. When an array /// has additional capacity and is not sharing its storage with another /// instance, appending an element is O(1). When an array needs to /// reallocate storage before appending or its storage is shared with /// another copy, appending is O(*n*), where *n* is the length of the array. /// /// - Parameter newElement: The element to append to the array. /// /// - Complexity: O(1) on average, over many calls to `append(_:)` on the /// same array. @inlinable @_semantics("array.append_element") publicmutatingfuncappend(_ newElement: __owned Element) { // Separating uniqueness check and capacity check allows hoisting the // uniqueness check out of a loop. _makeUniqueAndReserveCapacityIfNotUnique() let oldCount = _buffer.mutableCount _reserveCapacityAssumingUniqueBuffer(oldCount: oldCount) _appendElementAssumeUniqueAndCapacity(oldCount, newElement: newElement) _endMutation() }
/// Creates a new buffer, replacing the current buffer. /// /// If `bufferIsUnique` is true, the buffer is assumed to be uniquely /// referenced by this array and the elements are moved - instead of copied - /// to the new buffer. /// The `minimumCapacity` is the lower bound for the new capacity. /// If `growForAppend` is true, the new capacity is calculated using /// `_growArrayCapacity`. @_alwaysEmitIntoClient @inline(never) internalmutatingfunc_createNewBuffer( bufferIsUnique: Bool, minimumCapacity: Int, growForAppend: Bool ) { _internalInvariant(!bufferIsUnique || _buffer.isUniquelyReferenced()) _buffer = _buffer._consumeAndCreateNew(bufferIsUnique: bufferIsUnique, minimumCapacity: minimumCapacity, growForAppend: growForAppend) }
/// Creates and returns a new uniquely referenced buffer which is a copy of /// this buffer. /// /// If `bufferIsUnique` is true, the buffer is assumed to be uniquely /// referenced and the elements are moved - instead of copied - to the new /// buffer. /// The `minimumCapacity` is the lower bound for the new capacity. /// If `growForAppend` is true, the new capacity is calculated using /// `_growArrayCapacity`, but at least kept at `minimumCapacity`. /// /// This buffer is consumed, i.e. it's released. @_alwaysEmitIntoClient @inline(never) @_semantics("optimize.sil.specialize.owned2guarantee.never") internal __consuming func_consumeAndCreateNew( bufferIsUnique: Bool, minimumCapacity: Int, growForAppend: Bool ) -> _ArrayBuffer { let newCapacity = _growArrayCapacity(oldCapacity: capacity, minimumCapacity: minimumCapacity, growForAppend: growForAppend) letc = count _internalInvariant(newCapacity >= c) let newBuffer = _ContiguousArrayBuffer<Element>( _uninitializedCount: c, minimumCapacity: newCapacity)
/// 当buffer is Unique, 直接不进行copy,操作数据 if bufferIsUnique { // As an optimization, if the original buffer is unique, we can just move // the elements instead of copying. let dest = newBuffer.firstElementAddress dest.moveInitialize(from: mutableFirstElementAddress, count: c) _native.mutableCount = 0 } else { /// 进行复制 _copyContents( subRange: 0..<c, initializing: newBuffer.mutableFirstElementAddress) } return _ArrayBuffer(_buffer: newBuffer, shiftedToStartIndex: 0) }