【问题标题】:How can I get the memory address of a value type or a custom struct in Swift?如何在 Swift 中获取值类型或自定义结构的内存地址?
【发布时间】:2019-03-10 23:44:25
【问题描述】:

我正在尝试更深入地了解 Swift copies value types

您在代码中看到的行为总是好像复制了一份 地方。然而,斯威夫特只在幕后执行一个实际的复制 绝对必要时。

为了加深理解,我想获取一个值类型的内存地址。我尝试了 unsafeAddressOf(),但 this doesn't work with structs and it seems to cast Swift's standard library types to reference types(例如,String 被强制转换为 NSString)。

如何获取值类型的内存地址,例如 Int 的实例或 Swift 中的自定义结构?

【问题讨论】:

    标签: ios swift struct swift2 swift2.2


    【解决方案1】:

    根据 Martin R 的回答

    addressOf() 不能与结构变量一起使用。 String 是一个结构体,然而,当它被传递给期望一个对象的函数时,它会自动桥接到 NSString。

    根据 nschum 的回答,您可以像这样获取 struct、内置类型或对象引用的(堆栈)地址:

    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"
    

    我发现的一件事是,如果myStruct 没有值,地址将保持不变:

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

    【讨论】:

    • 所以这证明了 Swift 并没有为自定义 Struct 实现写时复制优化,只针对少数内置类型和类。很有趣。
    • @karansatia 类是引用类型,因此在分配时不会复制它们。如果将类实例分配给另一个对象,它们将指向同一个对象。因此,在上面的示例中,两个类的地址相同是正常的。它与写时复制无关。无论它们是内置类还是自定义类,都是如此。您必须实现 NSCopying 以使您的类可克隆,并以这种方式分配它: b = a.copy() as? MyClass 而不是 b = a
    【解决方案2】:

    我不确定是否有“推荐”的方法来做到这一点,但一种方法是使用withUnsafePointer(_:_:),如下所示:

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

    这在我的机器上打印了0x00007ffff52a011c8

    【讨论】:

    • Swift 4.2: withUnsafePointer(to: &s, { NSLog("($0)") })
    • @jreft56 你是对的,它与 Swift 5.2 相同
    【解决方案3】:

    斯威夫特 2.0:

    你可以用这个unsafeAddressOf(someObject)

    或在 Swift 3.0 中:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-05
      • 1970-01-01
      • 2017-06-14
      • 2018-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多