2016-05-23 30 views
7

Tôi đang cố gắng để đạt được một sự hiểu biết sâu sắc hơn về cách Swift copies value types:Làm cách nào để lấy địa chỉ bộ nhớ của loại giá trị hoặc cấu trúc tùy chỉnh trong Swift?

Các hành vi mà bạn nhìn thấy trong mã của bạn sẽ luôn là như thể một bản sao mất nơi. Tuy nhiên, Swift chỉ thực hiện một bản sao thực tế đằng sau hậu trường khi thực sự cần thiết.

Để nâng cao hiểu biết của mình, tôi muốn lấy địa chỉ bộ nhớ của loại giá trị. Tôi đã thử unsafeAddressOf(), nhưng this doesn't work with structs and it seems to cast Swift's standard library types to reference types (ví dụ: String được truyền tới NSString).

Làm cách nào để lấy địa chỉ bộ nhớ của loại giá trị, chẳng hạn như phiên bản Int hoặc cấu trúc tùy chỉnh trong Swift?

Trả lời

12

Theo câu trả lời Martin R' s

AddressOf() không thể được sử dụng với các biến struct. Chuỗi là một cấu trúc, tuy nhiên, nó được tự động bắc cầu đến NSString khi được chuyển đến một hàm mong đợi một đối tượng.

Theo câu trả lời nschum, bạn có thể lấy địa chỉ (chồng) của một struct , xây dựng-in loại hoặc đối tượng tham khảo như thế này:

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" 

Một điều tôi nhận thấy là, nếu myStruct không có giá trị, địa chỉ này sẽ được giữ lại giống nhau:

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

Vì vậy, điều này chứng tỏ rằng Swift không thực hiện tối ưu hóa copy-on-write cho Struct tùy chỉnh, chỉ cho một vài xây dựng trong loại và lớp học. Hấp dẫn. –

+0

@karansatia Lớp học là các loại tham chiếu, vì vậy chúng không được sao chép khi gán. Nếu bạn gán một cá thể lớp cho một đối tượng khác, chúng sẽ trỏ đến cùng một đối tượng. Do đó, điều bình thường là trong ví dụ trên chúng ta có cùng một địa chỉ cho cả hai lớp. Nó không liên quan gì đến việc sao chép. Điều này đúng cho dù chúng được xây dựng trong hay các lớp tùy chỉnh. Bạn phải thực hiện NSCopying để làm cho lớp của bạn cloneable, và gán nó theo cách này: b = a.copy() như? MyClass thay vì b = a –

3

Tôi không chắc chắn nếu có một "đề nghị" cách để làm điều đó, nhưng có một phương pháp là sử dụng withUnsafePointer(_:_:), như thế này:

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

này in 0x00007ffff52a011c8 trên máy tính của tôi.

6

Swift 2.0:

.210

Bạn có thể sử dụng này unsafeAddressOf(someObject)

hoặc trong Swift 3.0:

sử dụng withUnsafePointer(to: someObejct) { print("\($0)") }

Các vấn đề liên quan