繁体   English   中英

快速存储对数组的引用

[英]Storing a reference to array in swift

我想将一个数组传递给一个对象并存储对该数组的引用。 我希望能够在这个对象中修改这个数组,并确保它在其他任何地方都被修改。

这是我想要完成的(代码如何不起作用)

class Foo {
   var foo : Array<Int>

   init(foo: Array<Int>) {
      self.foo = foo
   }

   func modify() {
      foo.append(5)
   }
}

var a = [1,2,3,4]
let bar = Foo(a)
bar.modify()
print(a) // My goal is that it will print 1,2,3,4,5

到目前为止我的发现

A) 数组(默认情况下)以奇怪的方式传递。 在您修改数组长度之前,它是一个参考。 一旦您修改长度,它就会被复制和修改。 结果,如果我在对象中附加或删除它的任何内容,它就不会在外面看到

B) 我可以在函数参数上使用inout 这将允许我在此函数中修改它。 然而,一旦我尝试将它分配给某个对象成员,我再次被 A 击中)

C) 我可以在一些容器类中包装一个数组。 这可能是最干净的方法。 但是,我序列化/反序列化这些对象,我宁愿不把它放在 Container 中(因为我必须解决一些序列化和反序列化的问题,并将其发送到服务器)。

还有别的吗? 我是否缺少一些允许我这样做的 Swift 结构?

为此,您必须使用 NSArray 或 NSMutableArray,因为 Swift 数组是值类型,因此任何赋值都会创建一个副本。

您可以使用 Swifts(非常不敏捷) UnsafeMutablePointer

由于(从您的帖子中)对数组的行为引用似乎真的不可信,而是将UnsafeMutablePointer与类内部数组foo以及您想要绑定到foo的任何“外部”数组保持一致,在某种意义上它们都只是指向内存中相同地址的指针。

class Foo {
    var foo : [Int]
    var pInner: UnsafeMutablePointer<Int>

    init(foo: [Int]) {
        pInner = UnsafeMutablePointer(foo)
        self.foo = Array(UnsafeBufferPointer(start: pInner, count: foo.count))
    }

    func modify(inout pOuter: UnsafeMutablePointer<Int>) {
        foo.append(5) // <-- foo gets new memory adress
        pInner = UnsafeMutablePointer(foo)
        pOuter = pInner
    }
}

var a = [1,2,3,4] // first alloc in memory
var pOuter: UnsafeMutablePointer<Int> = UnsafeMutablePointer(a)
var bar = Foo(foo: a) // 'bar.foo' now at same address as 'a'
print(bar.foo) // [1,2,3,4]
bar.modify(&pOuter) // -> [1,2,3,4,5]
a = Array(UnsafeBufferPointer(start: pOuter, count: bar.foo.count))

/* Same pointer adress, OK! */
print(bar.pInner)
print(pOuter)

/* Naturally same value (same address in memory) */
print(bar.foo)
print(a)

虽然指针可能很危险(因此是合适的类型名称),而且非常不敏捷。 反正...

/* When you're done: clear pointers. Usually when using
   pointers like these you should take care to .destroy
   and .dealloc, but here your pointers are just companions
   to an Array property (which has a pointer an reference
   counter itself), and the latter will take care of the 
   objects in memory when it goes out of scope.            */
bar.pInner = nil
pOuter = nil

现在,当afoo超出范围时会发生什么,它会破坏没有超出范围的变量,还是 Swift 包含一些聪明的引用计数来实现内存地址仍在使用中? 我还没有对此进行调查,但请随意沉迷于此。

来自Swift 编程语言

Structures are always copied when they are passed around in your code, and do not use reference counting.

如果您检查数组变量的内容,您会发现追加确实有效:

class Foo {
  var foo : Array

  init(_ foo: Array) {
    self.foo = foo
  }

  func modify() {
    foo.append(5)
  }

  func printFoo() {
    print("self.foo: \(foo)")
  }
}

let a = [1,2,3,4]
let bar = Foo(a)
bar.modify()
bar.printFoo()
print("a: \(a)")

产生

self.foo: [1, 2, 3, 4, 5]
a: [1, 2, 3, 4]

您获取了 a 的副本,而不是对 a 的引用

a 被声明为常量,因此不能修改。 如果您打算修改 a 的内容,请将其声明为变量。 IE,

var a = [1,2,3,4]

我还没有测试过这个,但是,因为你正在使用一个类来包装数组,所以我看不出为什么下面的方法不起作用。

class Foo {
   var foo : Array<Int>

   init(foo: inout Array<Int>) {
      self.foo = foo
   }

   func modify() {
      foo.append(5)
   }
}

let a = [1,2,3,4]
let bar = Foo(&a)
bar.modify()
print("a: \(a)") // a: [1,2,3,4,5]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM