我基本上同意其他答案,你应该只使用map
,但是,如果你的数组真的非常巨大,并且为了将其转换为相同的位模式而创建整个第二个缓冲区真的很痛苦,那么可以像这样做:
func process<C: CollectionType where C.Generator.Element == UInt8>(chars: C) {
print(String(chars.map { UnicodeScalar($0) }))
}
let a: [Int8] = [104, 101, 108, 108, 111]
a.withUnsafeBufferPointer { buf -> Void in
process(
UnsafeBufferPointer(
start: UnsafePointer(buf.baseAddress),
count: buf.count))
}
注意,withUnsafeBufferPointer
的含义就是它的字面意思。如果使用不当,它是不安全的,可能会破坏内存(特别要小心使用计数器)。它基于你已知的外部知识来工作,例如,如果任何整数为负数,则您的代码不会在它们变成损坏的无符号整数时感到困扰。您可能知道这一点,但Swift类型系统不知道,因此它不允许在不使用不安全类型的情况下执行此操作。
尽管如此,上述代码是正确的,并且在规则内,这些技术是有正当理由的,前提是您需要性能优势。除非您处理大量数据或编写将被调用无数次的库,否则您几乎肯定不需要它们。
值得注意的是,存在某些情况下数组并不是由一个连续的缓冲区支持的(例如,如果它从 NSArray
转换而来),在这种情况下,调用.withUnsafeBufferPointer
会先将所有元素复制到一个连续的数组中。另外,Swift 数组是可变大小的,所以在数组增长时会经常发生底层元素的拷贝。如果性能绝对关键,您可以考虑使用 UnsafeMutablePointer
来分配自己的内存,并使用 UnsafeBufferPointer
风格来使用它。
对于一个有趣但绝对不符合规则的例子,您不应该使用以下代码:
process(unsafeBitCast(a, [UInt8].self))
值得注意的是,这些解决方案与
a.map { UInt8($0) }
不同,因为后者如果传入负整数会在运行时触发陷阱。如果存在这种可能性,则需要先进行过滤。