2016-05-23 21 views
7

Próbuję głębszego zrozumienia jak Swift copies value types:Jak mogę uzyskać adres pamięci typu wartości lub niestandardowej struktury w Swift?

Zachowanie widać w kodzie zawsze będzie tak, jakby kopia wziął miejsce. Jednak Swift wykonuje rzeczywistą kopię za sceną , gdy jest to absolutnie konieczne.

Aby lepiej zrozumieć, chciałbym uzyskać adres pamięci typu wartości. Próbowałem unsafeAddressOf(), ale this doesn't work with structs and it seems to cast Swift's standard library types to reference types (np. String jest rzutowany na NSString).

Jak mogę uzyskać adres pamięci typu wartości, na przykład instancji Int, lub niestandardowej struktury w Swift?

Odpowiedz

12

Według Martin R”s odpowiedź

AddressOf() nie może być stosowany ze zmiennymi struct. String jest strukturą, jednak jest automatycznie mostkowany do NSString po przekazaniu do funkcji oczekującej obiektu.

Według odpowiedź nschum, można uzyskać (stack) Adres struct, wbudowana typu lub obiektu jak poniżej:

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" 

Jedno znalazłem znaczy, jeśli myStruct nie ma żadnej wartości, adres będzie zachować ten sam:

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

Więc ten dowodzi, że Swift nie implementuje optymalizacji kopiowanie przy zapisie dla własnych strukturach, tylko dla nielicznych wbudowany typy i klasy. Ciekawy. –

+0

@karansatia Klasy są typami referencyjnymi, więc nie są kopiowane po przypisaniu. Jeśli przypiszesz instancję klasy do innego obiektu, wskażą ten sam obiekt. Dlatego jest normalne, że w powyższym przykładzie mamy ten sam adres dla obu klas. Nie ma to nic wspólnego z kopiowaniem na piśmie. Jest to prawda, niezależnie od tego, czy są to klasy wbudowane, czy niestandardowe. Musisz zaimplementować NSCopying, aby uczynić klasę sklonowaną i przypisać ją w następujący sposób: b = a.copy() as? MyClass a następnie b = a –

3

Nie jestem pewien, czy istnieje „zalecany” sposób to zrobić, ale jednym ze sposobów jest użycie withUnsafePointer(_:_:), tak:

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

Ten wydrukowany 0x00007ffff52a011c8 na moim komputerze.

6

Swift 2.0:

Można to wykorzystać unsafeAddressOf(someObject)

lub w Swift 3.0:

użytku withUnsafePointer(to: someObejct) { print("\($0)") }