Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Generics Swift闭包中保留内存的生存期_Generics_Swift_Memoization - Fatal编程技术网

Generics Swift闭包中保留内存的生存期

Generics Swift闭包中保留内存的生存期,generics,swift,memoization,Generics,Swift,Memoization,在WWDC 2014的高级Swift演讲中,演讲者给出了使用泛型的函数记忆器示例: func memoize<T: Hashable, U>( body: (T)->U ) -> (T)->U { var memo = Dictionary<T, U>() return { x in if let q = memo[x] { return q } let r = body(x) memo[x

在WWDC 2014的高级Swift演讲中,演讲者给出了使用泛型的函数记忆器示例:

func memoize<T: Hashable, U>( body: (T)->U ) -> (T)->U {
    var memo = Dictionary<T, U>()
    return { x in
        if let q = memo[x] { return q }
        let r = body(x)
        memo[x] = r
        return r
    }
}
func记忆(body:(T)->U)->(T)->U{
var memo=字典()
返回{x in
如果让q=memo[x]{return q}
设r=body(x)
备忘录[x]=r
返回r
}
}
我在思考
memo
var的生命周期时遇到了困难。memoized
fibonacci
函数的每次调用是否都强烈引用了它?如果是这样的话,那么在处理完内存后,您将如何释放该内存?

内部块(返回值)将保留memo,这意味着只要保留返回的blck,memo就会一直存在

每次调用memoize函数时,都会创建一个新的memo实例。调用返回的块不会创建新的备注实例


当返回的块超出范围时,内存将全部释放。

每次调用
memoize()
将创建自己的
memo
变量,与其他调用无关。它的寿命和它的生命一样长;当闭包被释放时,它捕获的变量(在本例中,
memo
)也被释放

您可以将此视为在以下伪代码中返回类似的结构:

struct Closure<T,U>
{
    var memo: Dictionary<T, U>
    func call(t: T): U
    {
        ....
    }
}

func memoize<T: Hashable, U>( body: (T)->U ) -> Closure<T,U>
{
    return Closure(memo: Dictionary<T, U>())
}
struct闭包
{
var备忘录:字典
函数调用(t:t):U
{
....
}
}
func memoize(主体:(T)->U)->闭包
{
返回闭包(备注:Dictionary())
}

在C/Objective-C块术语中,
memo
是一个
\u块
变量(在Swift中,通过引用捕获变量不需要显式写入
\u块
)。变量可以在块(闭包)中指定给,所有看到该变量的作用域都将看到来自任何其他变量的更改(它们共享对该变量的引用)。只要使用该变量的某个块(闭包)(在本例中只有一个块使用它)仍处于活动状态,该变量就有效。在最后一个使用它的块被释放后,变量将超出范围。如何工作是一个实现细节

如果此变量具有对象指针类型,则指向的对象将由捕获它的任何块保留。但是,在本例中,变量是
Dictionary
,它是一种结构类型,是一种值类型。因此,无需担心内存管理。变量就是结构,结构的寿命与变量的寿命一样长。(结构本身可以在其他地方分配内存,并在其析构函数中释放内存,但这完全由结构内部处理,外部不应该知道或关心它。)

人们通常不需要担心
\u块
变量如何在内部工作。但基本上,变量被包装在一个简化的“对象”类型的东西中,实际的“变量”是这个“对象”的一个字段,它是通过引用计数来管理内存的。捕获它们的块持有对这个伪对象的“强引用”——当在使用这个
\u block
变量的堆上创建一个块时(从技术上讲,当它们从堆栈块复制到堆上时),它会增加引用计数;当使用它的块被释放时,它会减少引用计数。当引用计数变为0时,这个伪“对象”被释放,首先为其变量类型调用相应的析构函数


为了回答您的问题,“记忆的斐波那契函数”是一个块(闭包)。这是一个对
memo
变量的引用。“调用”没有强引用或弱引用;调用函数时,它使用函数本身具有的引用。在本例中,
memo
变量的生存期是“记忆的斐波那契函数”的生存期,因为它是捕获该变量的唯一闭包。

它与该代码不同,因为多个闭包可以捕获该变量,并且该变量将在所有闭包之间共享状态。此外,变量状态也在闭包和闭包外的代码之间共享(即
memoize
函数中的代码也可以直接读写
memo
。@newacct代码是为了说明这种特殊情况,而不是一般的闭包。