Se si vuole il controllo completo su una regione di memoria allocare voi stessi, potete utilizzare UnsafePointer
e 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)
Si può anche avere UnsafePointer
punto a un'altra memoria, come la memoria si sta consegnato da alcune API C.
UnsafePointer
può essere passato in funzioni C che portano un puntatore a un blocco contiguo di memoria. Quindi, per i vostri scopi, si potrebbe quindi passare questo puntatore in una funzione simile 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)
È anche possibile tenere il proprio tipi personalizzati:
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)
Tuttavia essere a conoscenza se fare questo con le classi o anche array o stringhe (o una struttura che li contiene), che tutto ciò che si terrà nella memoria è puntatori ad altra memoria che questi oggetti allocano e possiedono. Se questo è importante per te (ad esempio stai facendo qualcosa di speciale in questa memoria, ad esempio la sicurezza, nel tuo esempio), probabilmente non è ciò che desideri.
Quindi è necessario utilizzare oggetti di dimensioni fisse o utilizzare ulteriormente UnsafePointer
per mantenere i puntatori su più aree di memoria. Se non hanno bisogno di ridimensionare dinamicamente, solo una singola allocazione di un puntatore non sicuro, possibilmente racchiuso in un interfaccia UnsafeBufferPointer
per un'interfaccia di raccolta, potrebbe farlo.
Se avete bisogno di un comportamento più dinamico, sotto è un'implementazione molto ridotta all'osso di una collezione che può ridimensionare, se necessario, che potrebbe essere valorizzato per coprire specialità memoria logica di gestione:
// 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 }
}
per coprire le requisiti di MutableCollectionType
(cioè CollectionType
più pedice assegnabile):
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)
}
}
E ExtensibleCollectionType
, per consentire la crescita dinamica:
Perché non si implementa semplicemente il metodo di deinit dell'oggetto che detiene la chiave e che cancella la chiave? – CouchDeveloper
@ 0x7fffffff - che tipo di informazioni aggiuntive stai cercando su ciò che la mia risposta ha dato? Avrò un tentativo di aggiungerlo. –
@AirspeedVelocity La risposta che hai dato è già eccezionale. Se non altro, sto solo cercando un altro esempio, o se possibile, una spiegazione di come si potrebbe cercare di aggirare i problemi associati con le stringhe e gli array. (principalmente solo stringhe) Grazie per il seguito. –