Swift 基礎學習(內存管理二)

/*
    Swift內存管理第二部分(高級)
(1)深淺拷貝
(2)字符串拷貝
(3)集合類的拷貝
(4)局部臨時對象和全局對象
(5)類型屬性的聲明週期
(6)隱式強引用-集合類,timer/元組
(7)閉包屬性引起的循環引用
(8)解決(7)的問題
*/

/*
(1)
*/
//結構體,值類型
struct Deep {
    var copy: Int = 0
}
//類,引用類型
class Shallow {
    var copy: Int = 0
}

//值類型的賦值操作是深拷貝
var d0 = Deep()
//深拷貝
//系統會分配一塊內存與d1進行綁定,也就是說d1指向這塊內存,這塊內存的內容等於d0指向的內存的內容,二者只是內容相同而已,但分別指向不同的內存
var d1 = d0
d1.copy = 9
//值不一樣就說明是兩份不同的拷貝,打印結果爲d0.copy爲0,d1.copy爲9
print(d0.copy)
print(d1.copy)

//引用類型的賦值操作是淺拷貝
//可能存在的問題:當多份引用同時指向一個對象時,如果對象提前釋放,就會出現內存泄露
var s0 = Shallow()
//淺拷貝
var s1 = s0
s1.copy = 9
//打印結構都是9
print(s0.copy)
print(s1.copy)


/*
(2)字符串拷貝
*/
var swiftStr: String = "Hello"
var swiftStr1 = swiftStr
swiftStr1 += "World"
//swiftStr1的變化如果會引起swiftStr變化就是淺拷貝,結構發現是深拷貝;簡單的方法我們可以直接看他們的類型
print(swiftStr)
print(swiftStr1)

//淺拷貝
var ocStr = NSMutableString(string: "Hello")
var ocStr1 = ocStr
ocStr1.insertString("World", atIndex: ocStr.length)
print(ocStr)
print(ocStr1)

/*
(3)集合類的拷貝
*/
//深拷貝
var array: Array<Int> = [1,2,3]
var array1 = array
array1 += [4,5,6]
print(array)
print(array1)

//深拷貝
var dict: Dictionary<Int, String> = [1:"a",2:"b"]
var dict1 = dict
dict1[3] = "c"
print(dict)
print(dict1)

//淺拷貝
var ocArray = NSMutableArray(array: [1,2,4])
var ocArray1 = ocArray
ocArray1.addObject(3)
print(ocArray)
print(ocArray1)

/*
(4)深入分析集合類的拷貝
//結構體,值類型
struct Deep {
var copy: Int = 0
}
//類,引用類型
class Shallow {
var copy: Int = 0
}
*/
var de0 = Deep()
var de1 = Deep()
//數組的元素都是值類型
var dearray = [de0,de1]

var sh0 = Shallow()
var sh1 = Shallow()
//數組的元素都是引用類型
var shaarray = [sh0, sh1]

//深拷貝
var dearray1 = dearray
var sharray1 = shaarray

/*
//當將數組中的某個元素替換,或者改變數組的大小,不會影響另外一個數組
dearray1.removeLast()
print(dearray1.count)
print(dearray.count)

dearray1[0] = Deep(copy: 3)
print(dearray1[0].copy)
print(dearray[0].copy)
*/

//(1)根據被拷貝數組的大小來創建一個新的數組對象,新的容量跟原始數組大小相同
//(2)將原始數組中的每一個元素依次拷貝到新的數組對象中
dearray1[0].copy = 88
print(dearray[0].copy)
print(dearray1[0].copy)

sharray1[0].copy = 99
print(shaarray[0].copy)
print(sharray1[0].copy)

/*
(5)隱式強引用
*/
class Student {
    var name: String
    init(name: String) {
        self.name = name
    }
    func show() {
        print("name = \(name)")
    }
    deinit {
        print("\(name) deinit!")
    }
}
//此時,stu0和stru1都引用了同一個對象
var stu0: Student? = Student(name: "Tom")
var stu1 = stu0
stu0 = nil
stu1 = nil

//Student(name: "zhangsan")
//Student(name: "lisi")
//對象加入到數組中,對象如果引用數據類型,那麼數組會強引用該對象
//數組讓該對象的引用計數加1
var stuarray: [Student]? = [Student(name: "zhangsan"), Student(name: "lisi")]
//(1)當某個對象不再屬於數組時,該對象的引用計數會減1
//(2)數組本身被銷燬的時候,它包含的所有對象不再屬於它,因此如果對象是引用數據類型,它的計數將會減1
//stuarray.removeAtIndex(0)
stuarray = nil

/*
(6)局部和全局引用
*/
//1.作用域 2.生命週期
//let ref: Int = Int(5)

if true {
    var ref: Student = Student(name: "xiaocui")
}

//全局引用作用域:定義的位置開始到文件的結尾處
var gloabal_ref = Int(8)
gloabal_ref = 10

//生命週期: 跟當前程序的生命週期相同
func testFunc() {
    gloabal_ref = 10
}

/*
(7)閉包屬性引起的循環引用
*/
class CycleRef {
    var a: Int = 9
    //如果閉包屬性中沒有直接或者間接訪問self,就不會產生循環強引用
    lazy var closure:() ->Void = {
        //默認閉包會對它訪問的對象執行強引用
//        [unowned self] in //解決方法
//        print("a=\(self.a)")

        //等同於
        [weak self] in
        print("a = \(self!.a)")
    }
    deinit {
        print("deinit")
    }
}
//兩個對象,閉包對象,cr指向的對象
//前提:閉包或者函數是引用數據類型.
var cr: CycleRef? = CycleRef()//引用計數:+1
cr!.closure()//引用計數: +1或+2...
cr = nil // -1
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章