指向数组元素的 UnsafeMutablePointer
UnsafeMutablePointer to an Array element
var a = [1,2,3]
let ptr1 = UnsafeMutablePointer<Int>(&a[0]) //works fine
let index = 0
let ptr2 = UnsafeMutablePointer<Int>(&a[index]) //compiler throws error
error: cannot invoke initializer for type UnsafeMutablePointer<Int>
with an argument list of type (inout Int)
为什么后一个编译不通过?我在这里遗漏了什么吗?
我想像下面的片段那样做。
class Holder {
var numbers: [Int] = [1,2,3,4]
var modifier: Modifier
init(index: Int) {
self.modifier = Modifier(UnsafeMutablePointer(&self.numbers) + index)
}
}
class Modifer {
var ptr: UnsafeMutablePointer<Int>
init(_ ptr: UnsafeMutablePointer<Int>) {
self.ptr = ptr
}
func change(to: Int) {
self.ptr.pointee = to
// expected the change to be reflected in numbers array
// but as Rob Napier said it became invalid and throws EXC_BAD_ACCESS
}
}
怎样才能达到上面的预期效果?
请注意,这些都不是创建 UnsafeMutablePointer 的有效方法。 Swift 可以在上次引用后立即释放 a,因此当您使用这些指针时,它们可能已经无效。您想要的工具是 a.withUnsafeMutableBufferPointer
.
也就是说,这里的正确语法是:
let ptr2 = UnsafeMutablePointer(&a) + index
查看您更新后的代码,这在 Array 上没有任何意义。我认为您假设数组是引用类型。它们是值类型。一块numbers
没办法改。对它的任何更改都会用一个完全不同的数组替换整个数组。 Swift 有一些聪明的 copy-on-write 技巧可以提高效率,在实践中它可能 实际上 替换整个数组,但您应该像它那样进行编程。您应该考虑以下行:
array[1] = 2
相当于:
array = <a new array that is identical, but element 1 has been replaced by 2>
这意味着指向 Array
的指针在非常受控的情况之外(例如在 withUnsafeMutableBufferPointer
块内)是没有意义的。
你想要的是这样的:
class Holder {
var numbers: [Int] = [1,2,3,4]
private(set) var modifier: ((Int) -> ())! // ! is an artifact of capturing self in init
init(index: Int) {
self.modifier = { [weak self] in self?.numbers[index] = [=13=] }
}
}
let holder = Holder(index: 2)
holder.numbers // [1, 2, 3, 4]
holder.modifier(0)
holder.numbers // [1, 2, 0, 4]
var a = [1,2,3]
let ptr1 = UnsafeMutablePointer<Int>(&a[0]) //works fine
let index = 0
let ptr2 = UnsafeMutablePointer<Int>(&a[index]) //compiler throws error
error: cannot invoke initializer for type
UnsafeMutablePointer<Int>
with an argument list of type(inout Int)
为什么后一个编译不通过?我在这里遗漏了什么吗?
我想像下面的片段那样做。
class Holder {
var numbers: [Int] = [1,2,3,4]
var modifier: Modifier
init(index: Int) {
self.modifier = Modifier(UnsafeMutablePointer(&self.numbers) + index)
}
}
class Modifer {
var ptr: UnsafeMutablePointer<Int>
init(_ ptr: UnsafeMutablePointer<Int>) {
self.ptr = ptr
}
func change(to: Int) {
self.ptr.pointee = to
// expected the change to be reflected in numbers array
// but as Rob Napier said it became invalid and throws EXC_BAD_ACCESS
}
}
怎样才能达到上面的预期效果?
请注意,这些都不是创建 UnsafeMutablePointer 的有效方法。 Swift 可以在上次引用后立即释放 a,因此当您使用这些指针时,它们可能已经无效。您想要的工具是 a.withUnsafeMutableBufferPointer
.
也就是说,这里的正确语法是:
let ptr2 = UnsafeMutablePointer(&a) + index
查看您更新后的代码,这在 Array 上没有任何意义。我认为您假设数组是引用类型。它们是值类型。一块numbers
没办法改。对它的任何更改都会用一个完全不同的数组替换整个数组。 Swift 有一些聪明的 copy-on-write 技巧可以提高效率,在实践中它可能 实际上 替换整个数组,但您应该像它那样进行编程。您应该考虑以下行:
array[1] = 2
相当于:
array = <a new array that is identical, but element 1 has been replaced by 2>
这意味着指向 Array
的指针在非常受控的情况之外(例如在 withUnsafeMutableBufferPointer
块内)是没有意义的。
你想要的是这样的:
class Holder {
var numbers: [Int] = [1,2,3,4]
private(set) var modifier: ((Int) -> ())! // ! is an artifact of capturing self in init
init(index: Int) {
self.modifier = { [weak self] in self?.numbers[index] = [=13=] }
}
}
let holder = Holder(index: 2)
holder.numbers // [1, 2, 3, 4]
holder.modifier(0)
holder.numbers // [1, 2, 0, 4]