詳談swift內(nèi)存管理中的引用計(jì)數(shù)
在swift中,每一個(gè)對(duì)象都有生命周期,當(dāng)生命周期結(jié)束會(huì)調(diào)用deinit()函數(shù)進(jìn)行釋放內(nèi)存空間。
觀察這一段代碼:
class Person{
var name: String
var pet: Pet?
init(name: String){
self.name = name
print("Person", name, "is initialized")
}
init(name: String, petName: String){
self.name = name
self.pet = Pet(name: petName)
print("Person", name, "is initialized")
}
deinit{
print("Person", name, "is deinitialized!")
}
}
class Pet{
var name: String
init(name: String){
self.name = name;
print("Pet", name, "is initialized")
}
deinit{
print("Pet", name, "is deinitialized!")
}
}
這段代碼創(chuàng)建了兩個(gè)類(lèi),分別是Person類(lèi)和Pet類(lèi),每個(gè)類(lèi)中都有init方法進(jìn)行創(chuàng)建對(duì)象和deinit方法來(lái)釋放內(nèi)存空間,其中Person類(lèi)中有兩個(gè)init方法,分別對(duì)應(yīng)著是否包含Pet類(lèi)的名稱(chēng)。
當(dāng)我們調(diào)用這兩個(gè)方法:
var snow: Person? = Person(name: "snow", petName: "wolf") snow = nil
兩步的執(zhí)行結(jié)果是:
Pet wolf is initialized Person snow is initialized Person snow is deinitialized! Pet wolf is deinitialized!
會(huì)發(fā)現(xiàn)在創(chuàng)建snow這個(gè)對(duì)象的時(shí)候調(diào)用的是第二個(gè)init方法,在這個(gè)方法中會(huì)創(chuàng)建一個(gè)新的Pet對(duì)象,因此會(huì)首先打印出Pet wolf is initialized然后是Person snow is initialized。當(dāng)對(duì)snow對(duì)象進(jìn)行內(nèi)存釋放的時(shí)候,將nil賦給這個(gè)對(duì)象,那么會(huì)釋放snow這個(gè)內(nèi)存空間,同時(shí)也會(huì)釋放wolf這個(gè)內(nèi)存空間。
但是如果我們調(diào)用第一種init方法的時(shí)候我們會(huì)發(fā)現(xiàn):
var snow: Person? = Person(name: "snow") var wolf: Pet? = Pet(name: "wolf") snow?.pet = wolf snow = nil wolf = nil
我們首先創(chuàng)建了一個(gè)snow對(duì)象,之后又創(chuàng)建了一個(gè)wolf對(duì)象,然后將wolf添加到snow對(duì)象中去,但是當(dāng)我們對(duì)這snow這個(gè)對(duì)象進(jìn)行內(nèi)存釋放的時(shí)候會(huì)發(fā)現(xiàn):
Person snow is initialized Pet wolf is initialized Person snow is deinitialized!
僅僅只有snow的內(nèi)存空間被釋放了,但是wolf的內(nèi)存空間并沒(méi)有被釋放,這里就和swift內(nèi)存管理中的引用計(jì)數(shù)有關(guān)了:
當(dāng)我們創(chuàng)建了snow這個(gè)對(duì)象之后,我們就為它開(kāi)辟了一個(gè)內(nèi)存空間,命名為a,這時(shí)候snow這個(gè)對(duì)象引用了這片內(nèi)存空間,這片內(nèi)存空間的引用計(jì)數(shù)就是1,
同樣地當(dāng)我們創(chuàng)建了wolf這個(gè)對(duì)象之后,我們就為它開(kāi)辟了一個(gè)內(nèi)存空間,命名為b,這時(shí)候wolf這個(gè)對(duì)象引用了這片內(nèi)存空間,這片內(nèi)存空間的引用計(jì)數(shù)就是1,
當(dāng)我們將snow?.pet = wolf之后,那么snow中的一個(gè)屬性也指向了創(chuàng)建wolf這個(gè)對(duì)象的內(nèi)存空間,那么這篇內(nèi)存空間的引用計(jì)數(shù)就是2.
當(dāng)我們對(duì)snow = nil進(jìn)行內(nèi)存空間的釋放,那么內(nèi)存空間a的引用計(jì)數(shù)就為0了,同時(shí)內(nèi)存空間b的引用計(jì)數(shù)就為1了。
當(dāng)系統(tǒng)發(fā)現(xiàn)一篇內(nèi)存空間的引用計(jì)數(shù)為0,那么,系統(tǒng)就會(huì)釋放這片內(nèi)存空間,此時(shí)內(nèi)存空間a就被釋放了。
但是內(nèi)存空間b的引用計(jì)數(shù)為1,系統(tǒng)不會(huì)進(jìn)行自動(dòng)的內(nèi)存釋放。只有當(dāng)我們進(jìn)行:
wolf = nil
操作之后,這片內(nèi)存空間b才會(huì)被釋放。
同樣地對(duì)于這樣代碼:
import UIKit
class Person{
var name: String
init(name: String){
self.name = name
print("Person", name, "is initialized")
}
deinit{
print("Person", name, "is being deinitialized!")
}
}
var person1: Person? = Person(name: "liuyubobobo")
var person2: Person? = person1
var person3: Person? = person1
那么person1的內(nèi)存空間的引用計(jì)數(shù)為3,如果釋放這片內(nèi)存空間的話,需要將三個(gè)對(duì)象都為nil
如果僅僅是將person1=nil的話,并不會(huì)釋放這一片內(nèi)存空間。
以上這篇詳談swift內(nèi)存管理中的引用計(jì)數(shù)就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Swift語(yǔ)言中字符串相關(guān)的基本概念解析
這篇文章主要介紹了Swift語(yǔ)言中字符串相關(guān)的基本概念解析,是Swift入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-11-11
Swift3遷移至Swift4可能遇到的問(wèn)題小結(jié)
每當(dāng)看到新的編程語(yǔ)言我總是會(huì)有相當(dāng)大的興趣,所以下面這篇文章主要給大家介紹了關(guān)于Swift3遷移至Swift4可能遇到的問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-06-06
Compose聲明式代碼語(yǔ)法對(duì)比React?Flutter?SwiftUI
這篇文章主要為大家介紹了Compose聲明式代碼語(yǔ)法對(duì)比React?Flutter?SwiftUI來(lái)解釋為什么說(shuō)?Compose?的聲明式代碼最簡(jiǎn)潔,有需要的朋友可以借鑒參考下2022-08-08
Swift 使用 Observe 監(jiān)測(cè)頁(yè)面滾動(dòng)的實(shí)現(xiàn)方法
這篇文章主要介紹了Swift 使用 Observe 監(jiān)測(cè)頁(yè)面滾動(dòng)的實(shí)現(xiàn)方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05
Swift并發(fā)系統(tǒng)并行運(yùn)行多個(gè)任務(wù)使用詳解
這篇文章主要為大家介紹了Swift并發(fā)系統(tǒng)并行運(yùn)行多個(gè)任務(wù)使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06

