如何为闭包分配内存?它的存储机制是什么? [英] How is memory allocated for closures & what is its storage mechanism?

查看:89
本文介绍了如何为闭包分配内存?它的存储机制是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想深入了解闭包及其分配和使用的机制。在阅读和使用它们一段时间后,我想到了一些确实让我头疼的问题:

I want to understand in depth about closures and their mechanism of being allocated and usage. After reading and using them a while I have come up with some questions that are really eating up my head:

问题-1
从内存分配的角度来看,闭包如何用作与普通变量不同的变量?

例如:让x:NSString = {}()& let x = NSString()

问题2
每个块的内存分配是如何发生的?

请对此进行解释,以使任何有类似疑问的读者都可以从中受益。

Please kindly explain these so as that any readers having similar kind of doubts might be beneficial from it.

**编辑*
Shadow对这个问题的回答是该问题的另一个方向。

推荐答案

对于具有默认值或默认闭包的存储属性,在 init 方法被调用。您不能使用 self 或用于通过默认值定义其他属性的属性。

For stored properties with default values or default closures memory allocates immideatly, before init method called. You can not use self or properties for defining other property by default value.

示例中的闭包通常用于此步骤定义 lazy 属性;它们应为 var 并标记为 lazy 关键字:

Closures from your example usually used on this step to define lazy properties; they should be var and marked with lazy keyword:

class myClass {
    let x: NSString? = nil
    let q: NSString? = {return "q"}() //allocates before class init; deallocates imidiatly
    lazy var y: NSString = {
        let z  = self.x
        return z ?? ""
    }()                               //allocates on first property call; deallocates imidiatly
}

惰性属性的内存将在第一个属性调用时分配。构造 {/*...*/}()意味着此闭包将仅在调用时刻执行,并将返回计算结果(您可以在未命名函数),不引用此闭包。这是非常重要的时刻:您不必保留闭包,该闭包仅分配给执行时刻,并在返回后立即释放,因此您无需关心强循环引用问题。

Memory for lazy properties will be allocated on first property call. Construction {/*...*/}() means that this closure will be executed just at call moment and will return result of calculation (you can look at this like at unnamed function), not reference to this closure. This is very important moment: you are not retain closure, this closure allocates only for execution moment and deallocates just after return, so you don't need care about strong cycle reference problem.

其他问题-保存对闭包的引用时:

Other thing - when you saving reference to closure:

class myClass {
    let x: NSString? = nil
    var closure: () -> NSString = {return "q"} //allocates before class init; deallocates on references release
    lazy var lazyClosure: () -> NSString = {
        let z  = self.x
        return z ?? ""
    }                                        //allocates on first property call; deallocates on references release
}

此闭包的内存分配与前面的情况相同,但它们将继续存在,直到有任何参考。您可以在这里查看闭包,就像在单独的对象上一样。此处可能会出现循环参考问题。 关闭不会捕获任何内容,因此没有任何问题,但是 lazyClosure 可以捕获自身。如果我们永远不会调用 lazyClosure ,那么将不会有任何问题,因为此闭包将永远不会分配。但是,如果我们调用它,它将被分配,它将捕获 self ,并且会有很强的循环参考: self 指向 lazyClosure 实例, lazyClosure 指向 self 实例。要解决此问题,您应该使引用之一变弱,应使用捕获列表:在中插入 [弱自我]或在<<中插入 [unown self] / code>在 lazyClosure 正文中。在我们的案例中, [unown self]位于中,因为如果调用了属性,则自我不是 nil

Memory for this closures allocates at same time as in previous case, but they will continue to live until have any references. You can look at closures here like at separate objects. Cycle reference problem can arise here. closure is not capture anything, so there are no problems with it, but lazyClosure capture self. If we will never call lazyClosure there will be no problems, since this closure will never allocates. But if we will call it, it will be allocated, it will capture self, and there will be strong cycle reference: self points to lazyClosure instance, lazyClosure points to self instance. To solve this problem you should make one of references weak, you should use capture list: insert [weak self] in or [unowned self] in in lazyClosure body. [unowned self] in in our case, since if property called, then self is not nil.

lazy var lazyClosure: () -> NSString = {
    [unowned self] in
    let z  = self.x
    return z ?? ""
}

这篇关于如何为闭包分配内存?它的存储机制是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆