在Swift 2中,三种阵列变体之间的主要区别是什么:
任何人都可以用现实世界的例子来解释这个吗?
答案 0 :(得分:12)
来自docs:
<强> ContiguousArray:强>
效率等同于Array的效率,除非T是类或@objc协议类型,在这种情况下使用ContiguousArray可能更有效。但请注意,ContiguousArray不会桥接到Objective-C。有关更多详细信息,请参阅与ContiguousArray共享大多数属性的数组。
基本上,只要您在数组中存储类或 @objc协议类型,您可能需要考虑使用ContiguousArray
而不是{{1 }}
<强> ArraySlice 强>
ArraySlice始终使用连续存储,不会桥接到Objective-C。
警告:不鼓励长期存储ArraySlice实例
因为ArraySlice会在一些较大的存储上显示视图 即使在原始数组的生命周期结束之后,也存储切片 可能会延长不再可访问的元素的生命周期, 这表现为明显的记忆和物体泄漏。阻止 这个效果,只使用ArraySlice进行瞬态计算。
当您想要从数组中获取子范围时,大多数情况下都会使用ArraySlices,例如:
Array
您应该使用let numbers = [1, 2, 3, 4]
let slice = numbers[Range<Int>(start: 0, end: 2)] //[1, 2]
。
答案 1 :(得分:1)
Swift定义了以下实现ArrayType协议的类; Array,ContiguousArray,Slice 。
Swift Array是表示数组的主类,该数组是一个采用1种类型的泛型类,整数数组的类型为Array<Int>
,创建一个整数数组:
var myArray = Array<Int>()
Slice是一个带有内部实现的数组,它使得从数组顶部删除元素的计算成本低廉。以下内容在Slice类型上表现良好:
var arr = [1,2,3,4,5]
arr[1…4]
没有太多关于ContiguousArray的文档,但从其名称可以猜测它与内部数组存储有关,可能元素存储在连续内存分配布局中。
答案 2 :(得分:1)
不同类别的Swift的好消息来源是:http://swiftdoc.org/
数组很清楚所以我们来谈谈其他两个。
ContiguousArray:http://swiftdoc.org/type/ContiguousArray/
快速,连续存储的T。
数组效率等同于Array的效率,除非T是一个类或 @objc协议类型,在这种情况下使用ContiguousArray可能更多 高效。但请注意,ContiguousArray不会桥接到 Objective-C的。请参阅与ContiguousArray共享最多的数组 属性,更多细节。
ArraySlice:http://swiftdoc.org/type/ArraySlice/
类似于Array的类型,表示任何Array的子序列, ContiguousArray或其他ArraySlice。
ArraySlice始终使用连续存储,但不会桥接 目标C
简而言之:
当T是类或@objc协议类型时,ContiguousArray可以提高效率 ArraySlice用于表示子部分中的Array。
答案 3 :(得分:1)
Apple提供了新的文档。 https://git.io/vg5uw
所以,
ContiguousArray<Element>
是三次使用中最快最简单的 这时你需要“C阵列”的表现。一个元素 ContiguousArray总是连续存储在内存中。
Array<Element>
与ContiguousArray<Element>
类似,但针对此进行了优化 来自Cocoa的高效转换和返回时Element可以是一个类 类型,Array<Element>
可以由(可能是非连续的)支持 存储任意NSArray而不是Swift ContiguousArray。Array<Element>
也支持上传和下传 在相关类类型的数组之间。当已知Element是一个 非类型,Array<Element>
的性能与此相同ContiguousArray<Element>
。
答案 4 :(得分:0)
这不是一个完整的答案。但是,Swift中带有少量gothcha的东西:
let array = [1,4,9,12,15]
您认为以下各项的值相同吗?
print(array[2..<5].index(of:12)) // is it 1 or 3?
print(array.index(of:12)) // 3
是的!因为两者都将打印3
。这是因为ArraySlice将不会获得自己的唯一副本(除非Array发生了突变)。 ArraySlice基本上是一种查看同一Array的某些索引的方法。它不会创建[9,12,15]的新数组并对其进行调查。它只会查看原始数组的给定范围。
现在怎么样?您认为以下内容是否相同?
print(array[2..<5].index(of:1)) // nil
print(array.index(of:1)) // 0
不! ArraySlice将打印nil
,而Array将打印0
显然:
print(array[2..<4][2]) // 9
print(array[2..<4][0]) // ERROR: out of bounds
又一次令人惊讶:
print(array.dropFirst(2).index(of:15)
不是不是 2
。它将返回4
作为其索引。为什么?因为dropFirst返回了ArraySlice
。如果您不希望它维护索引,则应该在ArraySlice之外构造一个新的Array ...
编辑:
来自docs:
与Array和ContiguousArray不同, ArraySlice的起始索引 实例并不总是为零。切片保持相同的索引 相同元素的较大数组,因此切片的起始索引 取决于它的创建方式,让您执行基于索引的 在完整阵列或切片上进行操作。
如果您对更多感兴趣。指向文档的链接还有另一个示例