2016-05-23 23 views
7

Sto cercando di acquisire una più profonda comprensione di come Swift copies value types:Come posso ottenere l'indirizzo di memoria di un tipo di valore o una struttura personalizzata in Swift?

Il comportamento che si vede nel codice sarà sempre come se una copia si è luogo. Tuttavia, Swift esegue solo una copia effettiva dietro le quinte quando è assolutamente necessario farlo.

Per migliorare la mia comprensione, mi piacerebbe ottenere l'indirizzo di memoria di un tipo di valore. Ho provato unsafeAddressOf(), ma this doesn't work with structs and it seems to cast Swift's standard library types to reference types (ad esempio, la stringa è trasmessa a NSString).

Come posso ottenere l'indirizzo di memoria di un tipo di valore, come un'istanza di Int o una struttura personalizzata in Swift?

risposta

12

Secondo la risposta s 'Martin R

AddressOf() non può essere utilizzato con le variabili struct. String è una struct, tuttavia viene automaticamente ponticellato su NSString quando viene passato a una funzione che si aspetta un oggetto.

Secondo la risposta di nschum, è possibile ottenere l'indirizzo (stack) di un struct, costruire-in di tipo o di un oggetto di riferimento in questo modo:

import UIKit 


func address(o: UnsafePointer<Void>) -> Int { 
    return unsafeBitCast(o, Int.self) 
} 

func addressHeap<T: AnyObject>(o: T) -> Int { 
    return unsafeBitCast(o, Int.self) 
} 


struct myStruct { 
    var a: Int 
} 

class myClas { 

} 
//struct 
var struct1 = myStruct(a: 5) 
var struct2 = struct1 
print(NSString(format: "%p", address(&struct1))) // -> "0x10f1fd430\n" 
print(NSString(format: "%p", address(&struct2))) // -> "0x10f1fd438\n" 

//String 
var s = "A String" 
var aa = s 
print(NSString(format: "%p", address(&s))) // -> "0x10f43a430\n" 
print(NSString(format: "%p", address(&aa))) // -> "0x10f43a448\n" 

//Class 
var class1 = myClas() 
var class2 = class1 
print(NSString(format: "%p", addressHeap(class1))) // -> 0x7fd5c8700970 
print(NSString(format: "%p", addressHeap(class2))) // -> 0x7fd5c8700970 

unsafeAddressOf(class1) //"UnsafePointer(0x7FD95AE272E0)" 
unsafeAddressOf(class2) //"UnsafePointer(0x7FD95AE272E0)" 

//Int 
var num1 = 55 
var num2 = num1 
print(NSString(format: "%p", address(&num1))) // -> "0x10f1fd480\n" 
print(NSString(format: "%p", address(&num2))) // -> "0x10f1fd488\n" 

Una cosa che ho trovato è, se myStruct non ha alcun valore, l'indirizzo verrà mantenere lo stesso:

struct myStruct { 

} 

var struct1 = myStruct() 
var struct2 = struct1 
print(NSString(format: "%p", address(&struct1))) // -> ""0xa000000000070252\n"" 
print(NSString(format: "%p", address(&struct2))) // -> ""0xa000000000070252\n"" 
+0

Quindi questo dimostra che Swift non implementa l'ottimizzazione copy-on-write per Structs personalizzati, solo per pochi costruita nel tipi e classi. Interessante. –

+0

@karansatia Le classi sono tipi di riferimento, quindi non vengono copiati durante l'assegnazione. Se assegni un'istanza di classe a un altro oggetto, puntano allo stesso oggetto. Quindi è normale che nell'esempio sopra abbiamo lo stesso indirizzo per entrambe le classi. Non ha nulla a che fare con la copia su scrittura. Questo è vero indipendentemente dal fatto che siano classi built-in o personalizzate. È necessario implementare NSCopying per rendere la classe clonabile e assegnarla in questo modo: b = a.copy() come? MyClass piuttosto che b = a –

3

non sono sicuro se c'è un modo "raccomandato" per farlo, ma un metodo è quello di utilizzare withUnsafePointer(_:_:), in questo modo:

var s: String = "foo" 
withUnsafePointer(&s) { NSLog("\($0)") } 

Questo stampato 0x00007ffff52a011c8 sulla mia macchina.

6

Swift 2.0:

.210

È possibile utilizzare questo unsafeAddressOf(someObject)

o in Swift 3.0:

uso withUnsafePointer(to: someObejct) { print("\($0)") }