如果您想完全控制自己分配的内存区域,可以使用UnsafePointer 和 co:
// allocate enough memory for ten Ints
var ump = UnsafeMutablePointer<Int>.alloc(10)
// memory is in an uninitialized raw state
// initialize that memory with Int objects
// (here, from a collection)
ump.initializeFrom(reverse(0..<10))
// memory property gives you access to the underlying value
ump.memory // 9
// UnsafeMutablePointer acts like an IndexType
ump.successor().memory // 8
// and it has a subscript, but it's not a CollectionType
ump[3] // = 6
// wrap it in an UnsafeMutableBufferPointer to treat it
// like a collection (or UnsafeBufferPointer if you don't
// need to be able to alter the values)
let col = UnsafeMutableBufferPointer(start: ump, count: 10)
col[3] = 99
println(",".join(map(col,toString)))
// prints 9,8,7,99,5,4,3,2,1,0
ump.destroy(10)
// now the allocated memory is back in a raw state
// you could re-allocate it...
ump.initializeFrom(0..<10)
ump.destroy(10)
// when you're done, deallocate the memory
ump.dealloc(10)
您还可以让UnsafePointer 指向其他内存,例如您由某些 C API 提供的内存。
UnsafePointer 可以传递给 C 函数,这些函数接受一个指向连续内存块的指针。因此,出于您的目的,您可以将此指针传递给像 mlock 这样的函数:
let count = 10
let ump = UnsafeMutablePointer.allocate<Int>(count)
mlock(ump, UInt(sizeof(Int) * count))
// initialize, use, and destroy the memory
munlock(ump, UInt(sizeof(Int) * count))
ump.dealloc(count)
您甚至可以拥有自己的自定义类型:
struct MyStruct {
let a: Int
let b: Int
}
var pointerToStruct = UnsafeMutablePointer<MyStruct>.alloc(1)
pointerToStruct.initialize(MyStruct(a: 1, b: 2))
pointerToStruct.memory.b // 2
pointerToStruct.destroy()
pointerToStruct.dealloc(1)
然而请注意,如果对类,甚至数组或字符串(或包含它们的结构)执行此操作,您将在内存中保存的只是指向这些对象的其他内存的指针分配和拥有。如果这对您很重要(例如,在您的示例中,您正在对此记忆做一些特殊的事情,例如保护它),那么这可能不是您想要的。
所以要么你需要使用固定大小的对象,要么进一步使用UnsafePointer 来保存指向更多内存区域的指针。如果他们不需要动态调整大小,那么只需分配一个不安全的指针,可能包装在一个集合接口的UnsafeBufferPointer 中,就可以做到这一点。
如果您需要更多动态行为,下面是一个可以根据需要调整大小的集合的非常简单的实现,可以对其进行增强以涵盖特殊的内存处理逻辑:
// Note this is a class not a struct, so it does NOT have value semantics,
// changing a copy changes all copies.
public class UnsafeCollection<T> {
private var _len: Int = 0
private var _buflen: Int = 0
private var _buf: UnsafeMutablePointer<T> = nil
public func removeAll(keepCapacity: Bool = false) {
_buf.destroy(_len)
_len = 0
if !keepCapacity {
_buf.dealloc(_buflen)
_buflen = 0
_buf = nil
}
}
public required init() { }
deinit { self.removeAll(keepCapacity: false) }
public var count: Int { return _len }
public var isEmpty: Bool { return _len == 0 }
}
为了满足MutableCollectionType 的要求(即CollectionType 加上可分配的下标):
extension UnsafeCollection: MutableCollectionType {
typealias Index = Int
public var startIndex: Int { return 0 }
public var endIndex: Int { return _len }
public subscript(idx: Int) -> T {
get {
precondition(idx < _len)
return _buf[idx]
}
set(newElement) {
precondition(idx < _len)
let ptr = _buf.advancedBy(idx)
ptr.destroy()
ptr.initialize(newElement)
}
}
typealias Generator = IndexingGenerator<UnsafeCollection>
public func generate() -> Generator {
return Generator(self)
}
}
还有ExtensibleCollectionType,以实现动态增长:
extension UnsafeCollection: ExtensibleCollectionType {
public func reserveCapacity(n: Index.Distance) {
if n > _buflen {
let newBuf = UnsafeMutablePointer<T>.alloc(n)
newBuf.moveInitializeBackwardFrom(_buf, count: _len)
_buf.dealloc(_buflen)
_buf = newBuf
_buflen = n
}
}
public func append(x: T) {
if _len == _buflen {
reserveCapacity(Int(Double(_len) * 1.6) + 1)
}
_buf.advancedBy(_len++).initialize(x)
}
public func extend<S: SequenceType where S.Generator.Element == T>
(newElements: S) {
var g = newElements.generate()
while let x: T = g.next() {
self.append(x)
}
}
}