【问题标题】:Inout parameters don't have the same addressinout 参数没有相同的地址
【发布时间】:2016-03-16 16:12:26
【问题描述】:

我有三个类 A、B 和 C。A 有一个名为 rA 的资源。我想要实现的是所有这些实例都引用了完全相同的资源。

所以用 Swift 术语来具体说明:

A 类有一个名为 foo 的属性:

private var foo : [Bar] = [Bar]() // shared resource

B 类有一个名为 foo 的属性,它作为 inout 参数传递给初始化程序:

private var foo : [Bar]!
init(inout foo:[Bar]){
    self.foo = foo
}

C 类类似于 B 类

如果我将 foo 从 A 类传递到 B 类(或 C),地址会改变吗?

在 A 中,我会将其传递给 B(或 C),如下所示:

let b = B(foo: &self.foo)

当我在 A 中初始化 foo 后打印地址时,它给我的地址与在 B 中分配后的地址不同。

class A{
    private var foo = [Bar]()
    func someFunc(){
        NSLog("\n\n [A] \(unsafeAddressOf(self.foo))\n\n") // different from output in B
        let b = B(foo: &self.foo)

    }
}

class B{
    private var foo: [Bar]!
    init(inout foo: [Bar]){
         self.foo = foo
         NSLog("\n\n [B] \(unsafeAddressOf(self.foo))\n\n")
    }
}

任何想法为什么会这样?

【问题讨论】:

  • unsafeAddressOf() 采用AnyObject 参数,因此在您的情况下,类型为[Bar] 的Swift 数组桥接到NSArray。这种桥接可能会也可能不会在重复执行时产生相同的对象。
  • @MartinR 谢谢,这是有道理的。有没有其他方法可以检查它们是否引用同一个对象?
  • 请注意,Swift 数组是 值类型self.foo = foo“复制”数组(即使实际元素仅按需复制)。 – 如果您需要一个可以传递的真实 reference,那么您可以将数组包装在 class 中。或者使用NS(Mutable)Array,但你会失去许多 Swift 功能。
  • 这就是我爱你的原因@MartinR。总是非常有帮助。把你的cmets打包成答案,我会奖励你的!

标签: ios swift pass-by-pointer inout


【解决方案1】:

Swift 数组是值类型,因此在

self.foo = foo

您将foo 分配给self.foo。现在这是两个独立的数组 (即使只有在其中一个数组发生突变时才复制实际元素)。

您也不能使用unsafeAddressOf() 获取 Swift 数组的地址,因为 该函数采用AnyObject 参数,该参数是类的实例,即 值类型。在

 unsafeAddressOf(self.foo)

Swift 编译器实际上将 Swift 数组连接到 NSArray。如图所示 在Swift, Strings and Memory Addresses, 重复执行时,这可能会或可能不会导致相同的对象。在任何情况下, 打印出来的地址不是 Swift 数组的存储位置。

如果您需要一个可以传递的真实引用,那么您可以将数组包装在一个类中。 使用NS(Mutable)Array 也可能是一种选择,但你会失去许多 Swift 功能。

【讨论】:

    猜你喜欢
    • 2020-05-23
    • 1970-01-01
    • 1970-01-01
    • 2012-12-16
    • 1970-01-01
    • 2021-06-29
    • 1970-01-01
    • 2015-09-21
    • 2021-04-22
    相关资源
    最近更新 更多