在手动构造Swift UnsafeMutablePointer时,在alloc之后是否必须使用destroy/dealloc?

mat*_*att 9 memory-management swift

让我们说在Swift中我手动构造一个C数组并传递它,如下所示:

override func drawRect(rect: CGRect) {
    let c = UIGraphicsGetCurrentContext()
    var arr = UnsafeMutablePointer<CGPoint>.alloc(4)
    arr[0] = CGPoint(x:0,y:0)
    arr[1] = CGPoint(x:50,y:50)
    arr[2] = CGPoint(x:50,y:50)
    arr[3] = CGPoint(x:0,y:100)
    CGContextStrokeLineSegments(c, arr, 4)
}
Run Code Online (Sandbox Code Playgroud)

(我知道我不会这样做,只是我承担.)如果我不叫destroy和/或dealloc在此UnsafeMutablePointer,我会泄漏内存四个CGPoints?

Air*_*ity 12

文档UnsafeMutablePointer很清楚:

///                      This type provides no automated
/// memory management, and therefore the user must take care to allocate
/// and free memory appropriately.
Run Code Online (Sandbox Code Playgroud)

因此,如果您分配但不解除分配,则会泄漏内存.在销毁指针对象时没有自动释放.

在解除分配之前你是否应该销毁,这也很清楚:

/// The pointer can be in one of the following states:
///
/// - memory is not allocated (for example, pointer is null, or memory has
/// been deallocated previously);
///
/// - memory is allocated, but value has not been initialized;
///
/// - memory is allocated and value is initialized.
Run Code Online (Sandbox Code Playgroud)

但请记住,您可以在这些状态之间来回转换.因此,在分配然后初始化然后去初始化(也就是销毁)对象之后,内存不再处于"初始化"状态,因此您可以重新初始化或取消分配它.您也可以分配,然后解除分配,而无需进行初始化.

当打电话时dealloc:

/// Deallocate `num` objects.
...
/// Precondition: the memory is not initialized.
///
/// Postcondition: the memory has been deallocated.
Run Code Online (Sandbox Code Playgroud)

因此,在调用之前,必须在任何已初始化的对象上调用destroy dealloc.你可能是正确的,因为类似的东西CGPoint是完全惰性的(只是两个浮点数的结构),在你打电话之前不打电话可能没有任何伤害,但你不能确定在不知道实施的情况下指针结构和编译器可能,因为标准的lib是语言的一部分,可能会有一些烘焙优化),而且一般来说,这不是一个好习惯.迟早你会忘记摧毁一个,然后你会后悔的.destroydeallocString

(这些都没有解释move将初始化新内存与破坏旧内存相结合的操作btw)

如果你希望通过某种自动化的内存自清理UnsafePointer,我认为这不可能,因为a)它是一个结构,所以deinit当超出范围时不能实现自动解除分配,并且b )它不跟踪它自己的大小 - 你必须跟踪你分配的数量,并在调用中明确地提供它deallocate.

标准库中有一些东西可以自动释放内存而无需自己动手 - HeapBufferStorage标准库中唯一的类.据推测,这是一个特别受益于实施的类deinit.还有HeapBuffer管理它,它有一个方便的isUniquelyReferenced()功能,允许你告诉它是否被复制(即使它是一个结构),因此将允许你实现类似于数组和字符串的写时复制功能.


poi*_*tum 6

在Swift 2中,通过将alloc/dealloc与new defer关键字配对,可以使UnsafeMutablePointer不那么令人沮丧:

let ptr = UnsafeMutablePointer<T>.alloc(1)
defer { ptr.dealloc(1) }
Run Code Online (Sandbox Code Playgroud)