【问题标题】:How is memory allocated for closures & what is its storage mechanism? [closed]如何为闭包分配内存以及它的存储机制是什么? [关闭]
【发布时间】:2017-01-02 02:32:18
【问题描述】:

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

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

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

问题 2 块的内存分配究竟是如何发生的?

请解释这些,以便任何有类似疑问的读者从中受益。

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

【问题讨论】:

  • 你的帖子太宽泛了,你的一些问题已经在这里得到解答,例如stackoverflow.com/questions/32693150/…
  • @Cristik 我已经编辑了我的问题。你能回答编辑过的问题吗?谢谢。

标签: ios swift closures


【解决方案1】:

对于具有默认值或默认闭包的存储属性,内存会在调用init 方法之前立即分配。您不能使用self 或属性来默认定义其他属性。

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

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
}

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

其他事情 - 当您保存对闭包的引用时:

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
}

此闭包的内存分配与前一种情况相同,但它们将继续存在,直到有任何引用。您可以在这里查看闭包,就像查看单独的对象一样。这里可能会出现循环引用问题。 closure 没有捕获任何东西,所以它没有问题,但是lazyClosure 捕获self。如果我们永远不会调用lazyClosure 就不会有问题,因为这个闭包永远不会分配。但是如果我们调用它,它就会被分配,它会捕获self,并且会有强循环引用:self指向lazyClosure实例,lazyClosure指向self实例。要解决此问题,您应该使引用之一变弱,您应该使用捕获列表:在lazyClosure 正文中插入[weak self] in 或[unowned self] in。 [unowned self] in 在我们的例子中,因为如果调用了属性,那么 self 不是 nil。

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

【讨论】:

  • 感谢您的回复,但您能否修改您的答案并包括创建时块的内存分配与对象之间的区别?
  • @G.Abhisek 我修改了答案并更正了错误,看看
  • 抱歉回复晚了。一个小的澄清-a)在闭包本身的范围内声明的变量呢?它们的内存分配是如何发生的?
  • @G.Abhisek 这种内存分配发生在函数中(实际上它们是闭包)。更广泛地说,闭包中的代码依赖于顺序,变量的内存仅在声明点分配,并且某些代码部分永远无法执行(永远不会分配该变量的内存)。使用return 语句释放内存(保留的引用当然可以继续存在;例如,当您返回对象的引用时)。闭包中的变量不像属性,例如你不能用lazy关键字标记它们。每个调用结果的闭包都有自己的范围。
猜你喜欢
  • 2011-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-10
  • 2015-12-16
相关资源
最近更新 更多