js 内存引用计数_快速内存管理–自动引用计数

js 内存引用计数

In this tutorial, we’ll be covering Swift memory management and learn about Automatic Reference Counting (ARC) in Swift. It’s an essential concept and is useful in preventing memory leaks in our iOS Applications.

在本教程中,我们将介绍Swift内存管理,并了解Swift中的自动引用计数(ARC)。 这是必不可少的概念,对于防止我们的iOS应用程序中的内存泄漏很有用。

We’ll be covering the following concepts:

我们将介绍以下概念:

  • What is ARC and how does it work?

    什么是ARC?如何运作?
  • Resolving Strong Reference Cycles

    解决强大的参考周期
  • Differences between strong, weak and unowned references

    强引用,弱引用和无所有权引用之间的差异
  • Strong Reference Cycles in Closures

    封闭的强大参考周期
  • Resolving Reference Cycles in Closures using Capture Lists

    使用捕获列表解决封闭中的参考循环

快速内存管理–自动引用计数 (Swift Memory Management – Automatic Reference Counting)

Automatic Reference Counting is an underlying tool that takes care of allocating and freeing memory for references. It keeps a track of the count of references for an object.

自动引用计数是一个基础工具,负责分配和释放引用的内存。 它跟踪对象的引用计数。

How does it allocate?
When an object is initialised, ARC assigns it a chunk of memory. That memory holds information about that object, such as its properties, constants, references it is linked to. Further reading – swift init function.

如何分配?
初始化对象后,ARC会为其分配一块内存。 该内存保存有关该对象的信息,例如其属性,常量,链接到的引用。 进一步阅读- 快速初始化功能

How does it deallocate?
ARC keeps a count of the number of references to the object. It cannot deallocate the object when there are references since that might lead to runtime crashes. Once the reference count is 0, it deallocates the object by calling the deinit() and frees up the memory.

如何分配?
ARC会记录对对象的引用数量。 存在引用时,它无法取消分配对象,因为这可能导致运行时崩溃。 一旦引用计数为0,它将通过调用deinit()释放对象并释放内存。

Note: ARC and memory management do not guarantee to work perfectly in XCode Playgrounds as they do in XCode projects. Nevertheless, since the focus of this post is ARC and not iOS Applications, we’re using playgrounds below, just for the sake of convenience.

注意:ARC和内存管理不能保证在XCode Playgrounds中能像在XCode项目中那样完美地工作。 不过,由于本文的重点是ARC,而不是iOS应用程序,为方便起见,我们在下面使用游乐场。

Swift ARC实战 (Swift ARC in Action)

Let’s create a swift class and then instantiate it.

让我们创建一个swift类 ,然后实例化它。

import Foundation

class Student {
    let name: String
    var website  = "JournalDev"
    init(name: String) {
        self.name = name
        print("\(name) is being initialized")
    }
    deinit {
        print("\(name) is being deinitialized")
        print("\(website) is being deinitialized")
    }
}
var s : Student? = Student(name: "Anupam")
var reference = s //reference count is 2
var reference2 = reference //reference count is 3
//prints
//Anupam is being initialized

To deallocate the object, we need to remove the references.

要取消分配对象,我们需要删除引用。

reference = nil
s = nil
reference2 = nil
//prints
//Anupam is being deinitialized
//JournalDev is being deinitialized

In the above code, deinit block is run automatically by the ARC. You cannot call it manually.
We’ve created references of type Optional so that if they’re invoked in the future, it won’t cause a crash.
Setting the references as nil lets the ARC change the reference count.

在上面的代码中, deinit块由ARC自动运行。 您无法手动调用。
我们创建了Optional类型的引用,以便将来调用它们时不会导致崩溃。
将引用设置为nil可使ARC更改引用计数。

Note: ARC is NOT a garbage collector. ARC can only clear memory if it unused. In some cases the programmer needs to help ARC to clear the memory and prevent memory leaks as we shall see in the next section.

注意 :ARC不是垃圾收集器。 ARC仅可清除未使用的内存。 在某些情况下,程序员需要帮助ARC清除内存并防止内存泄漏,这将在下一部分中看到。

解决强大的参考周期 (Resolving Strong Reference Cycles)

By default, the ARC creates a strong reference. Now we can have scenarios where there are reference cycles as shown in the code below.

默认情况下,ARC创建强引用。 现在,我们可以在场景中存在参考循环,如下面的代码所示。

class Student {
    let name: String
    init(name: String) { self.name = name }
    var university: University?
    deinit { print("\(name) is being deinitialized") }
}

class University {
    let uniName: String
    init(uniName: String) { self.uniName = uniName }
    var student: Student?
    deinit { print("University \(unit) is being deinitialized") }
}

Each of the classes has a reference to the other. Let’s initialise them.

每个类都有对另一个的引用。 让我们初始化它们。

var me: Student?
var uni: University?

me = Student(name: "John Doe")
uni = University(uniName: "IIT")

me?.university = uni
uni?.student = me

This creates a strong reference between both the classes. Something that the below illustration rightly depicts.

这在两个类之间创建了强大的参考。 下图正确描绘了一些东西。

Let’s see how the strong references impact the lifecycle of the objects.

让我们看看强引用如何影响对象的生命周期。

me=nil
uni=nil

//Does nothing

We’ve set the references to nil, to let ARC deallocate them but it doesn’t happen.
Strong Reference Cycle is created in the above code that is a potential cause of memory leaks!

我们将引用设置为nil,以使ARC取消分配它们,但不会发生。
上面的代码中创建了强引用循环,这可能是内存泄漏的潜在原因!

Before we get into resolving the strong references let’s look at other types of references.

在解决强引用之前,让我们看一下其他类型的引用。

强,弱,无主引用 (strong, weak, unowned references)

  • strong references are the standard type of references created by default.

    引用是默认创建的标准引用类型。
  • weak references allow instance creations but do not add up in the reference count of the ARC. Typically a reference should be marked as weak when it has a shorter lifetime than the other reference.

    引用允许创建实例,但不将ARC的引用计数加起来。 通常,参考寿命短于其他参考时,应将其标记为弱。
  • unowned references are similar to weak references except that they’re used on references that have a longer lifetime than the other reference.

    无主引用与弱引用相似,不同之处在于它们用于寿命比其他引用更长的引用。
  • An unowned reference should be used only when you’re absolutely sure that the reference does exist there otherwise if it’s invoked on a nil reference it’ll crash.

    仅当您绝对确定该引用确实存在时,才应使用无主引用,否则,如果在nil引用上调用该引用,则会崩溃。
  • A weak reference can be used when the reference is nil.

    当引用为零时,可以使用引用。

解决强大的参考周期 (Resolving Strong Reference Cycles)

We can resolve strong reference cycles in the above example by making any one of the references as weak or unowned references. Such references do not add to the reference count in the ARC.

在上面的示例中,我们可以通过将任意一个引用设为弱引用或无主引用来解决强引用周期。 此类引用不会添加到ARC中的引用计数中。

class Student {
    let name: String
    init(name: String) { self.name = name }
    var university: University?
    deinit { print("\(name) is being deinitialized") }
}

class University {
    let uniName: String
    init(uniName: String) { self.uniName = uniName }
    weak var student: Student?
    deinit { print("University \(uniName) is being deinitialized") }
}

Initialising the references and then setting then nil would now call the deinit statement.

初始化引用,然后设置nil现在将调用deinit语句。

var me: Student?
var uni: University?

me = Student(name: "John Doe")
uni = University(uniName: "IIT")

me?.university = uni
uni?.student = me

me=nil
uni=nil

//prints
//John Doe is being deinitialized
//University IIT is being deinitialized

Note: Setting unowned reference in the above example would cause a crash since unowned reference cannot be set to nil.

注意:由于无法将无主引用设置为nil,因此在上面的示例中设置无主引用会导致崩溃。

使用捕获列表解决封闭中的参考循环 (Resolving Reference Cycles in Closures using Capture Lists)

Closures are reference types. Hence they can have a strong reference cycle created as shown below:

闭包是参考类型。 因此,它们可以创建一个强大的参考周期,如下所示:

class User {
    
    let name: String
    let skill: String
    
    lazy var summary: () -> String = {
        return "\(self.name) (\(self.skill))"
    }
    
    init(name: String, skill: String) {
        self.name = name
        self.skill = skill
    }
    
    deinit {
        print("Deallocated User")
    }
    
}

Let’s allocate and deallocate an object.

让我们分配和释放对象。

var name: User? = User(name: "Anupam", skill: "Swift")

name?.summary()

name = nil

//deinit NOT called.

Because closures are reference types they create a strong reference cycle by capturing the self reference. Hence the reference count can never be zero.
Let’s try resolving this.

因为闭包是引用类型,所以它们通过捕获self引用来创建强大的引用周期。 因此,参考计数永远不能为零。
让我们尝试解决这个问题。

捕获列表 (Capturing Lists)

We can use self as a weak or unowned reference inside the closure as shown below.

我们可以将self用作闭包内部的弱引用或无主引用,如下所示。

lazy var summary: () -> String = {[unowned self] in
        return "\(self.name) (\(self.skill))"
    }

We explcitly pass a list passing an unowned reference of self.

我们明确地传递了一个列表,该列表传递了自己的无主引用。

As we known from Closures, the parameters are separated from the return type by the in keyword.
With that the strong reference cycle in closures is resolved.

从闭包中我们知道,参数通过in关键字与返回类型分开。
这样就解决了闭包中强大的参考周期。

That’s all for quick roundup on swift memory management and automatic resource counting feature.

这就是快速存储管理和自动资源计数功能的快速汇总。

Reference: Apple Docs

参考: Apple Docs

翻译自: https://www.journaldev.com/19619/swift-memory-management-automatic-reference-counting

js 内存引用计数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值