让我们说在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)
}
(我知道我不 这样做,但只是忍受我。)如果我不打电话给destroy
和/或dealloc
UnsafeMutablePointer,我是否泄漏了4个CGPoints的内存?
答案 0 :(得分:12)
UnsafeMutablePointer
的文档非常明确:
/// This type provides no automated
/// memory management, and therefore the user must take care to allocate
/// and free memory appropriately.
因此,如果您分配但不解除分配,则会泄漏内存。在销毁指针对象时没有自动释放。
关于你是否应该在解除分配之前销毁它,它也很清楚:
/// 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.
但请记住,你可以在这些状态之间来回转换。因此,在分配然后初始化然后去初始化(也就是销毁)对象之后,内存不再处于“初始化”状态,因此您可以重新初始化或取消分配它。您也可以在不进行初始化的情况下进行分配,然后解除分配。
致电dealloc
时:
/// Deallocate `num` objects.
...
/// Precondition: the memory is not initialized.
///
/// Postcondition: the memory has been deallocated.
因此,在调用dealloc
之前,必须在任何已初始化的对象上调用destroy。你可能是对的,因为像CGPoint
这样的东西是完全惰性的(只是两个浮点数的结构),可能不会有任何伤害而不能调用destroy
在你调用dealloc
之前,你可能不确定实现(可能是指针结构和编译器),因为标准的lib是语言的一部分,可能会有一些优化),一般来说,这不是一个好习惯。迟早你会忘记摧毁String
,然后你会后悔。
(这些都没有说明将新内存与破坏旧内存相结合的move
操作btw)
如果你希望通过UnsafePointer
进行某种自动的内存自清理,我认为这不可能,因为a)它是一个结构,所以无法实现{{1}当超出范围时自动解除分配,并且b)它不跟踪它自己的大小 - 你必须跟踪你分配的数量,并在调用deinit
时明确地提供它。
标准库中有一些东西可以自动释放内存而无需自己执行 - deallocate
,这是标准库中唯一的类。据推测,这是一个专门从HeapBufferStorage
的实现中受益的类。还有deinit
来管理它,这有一个方便的HeapBuffer
函数,允许你判断它是否被复制(即使它是一个结构),因此可以让你实现copy-on-写入与数组和字符串类似的功能。
答案 1 :(得分:0)
这适用于像我这样通过搜索CGContextStrokeLineSegments找到此问题/答案主题的人。如果您的目的是在Swift中调用此函数,则即使函数的第二个参数是UnsafeMutablePointer,也不必构造C数组指针。你可以直接将一个Swift数组传递给它,即使是一个不可变的数组,而不是带有分配和释放的C指针。例如:
override func drawRect(rect: CGRect) {
if let c = UIGraphicsGetCurrentContext()
{
let arr = [CGPoint(x:0,y:0), CGPoint(x:50,y:50), CGPoint(x:50,y:50), CGPoint(x:0,y:100)]
CGContextStrokeLineSegments(c, arr, 4)
}
}