[英]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
现在,当a
或foo
超出范围时会发生什么,它会破坏没有超出范围的变量,还是 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.