Sobes.tech
Middle

Kas yra automatinis nuorodų skaičiavimas?

sobes.tech AI

Atsakymas iš AI

Automatinis nuorodų skaičiavimas (Automatic Reference Counting, ARC) yra atminties valdymo mechanizmas Swift ir Objective-C kalbose, kuris automatiškai stebi ir atlaisvina objektams paskirtą atmintį. Kiekvienas klasės egzempliorius turi nuorodų skaitiklį, kuris didėja, kai sukuriama stipri nuoroda į objektą, ir mažėja, kai ji pašalinama. Kai nuorodų skaitiklis pasiekia nulį, ARC automatiškai atlaisvina objektą ir užimamą atmintį.

ARC užkerta kelią atminties nutekėjimams ir dvigubam atlaisvinimui, supaprastindamas atminties valdymą, palyginti su rankiniu valdymu (pavyzdžiui, Objective-C be ARC).

Yra trys nuorodų tipai:

  1. Strong (Stipri): Padidina objekto nuorodų skaitiklį. Tai numatytasis nuorodų tipas.
  2. Weak (Silpna): Nepadidina nuorodų skaitiklio. Naudojama siekiant išvengti stiprių nuorodų ciklų, kai du objektai stipriai nuorodo vienas į kitą. Silpna nuoroda tampa nil, jei nuoroda nukreipia į objektą, kuris buvo atlaisvintas. Apibrėžiama žodžiu weak.
  3. Unowned (Nepriklausoma): Nepadidina nuorodų skaitiklio ir visada turi reikšmę. Naudojama, kai žinoma, kad nuoroda visada nukreips į objektą, kol jis egzistuoja. Skirtingai nuo weak, unowned nuoroda nepasidaro nil ir gali sukelti klaidą, jei bandysite pasiekti objektą po jo atlaisvinimo. Apibrėžiama žodžiu unowned.

Pavyzdys stiprių nuorodų ciklo:

class Human {
    let name: String
    var apartment: Apartment? // Opciobalus `Apartment` stipri nuoroda
    init(name: String) {
        self.name = name
        print("\(name) pradedama inicializacija")
    }
    deinit {
        print("\(name) baigiasi deinitialization")
    }
}

class Apartment {
    let unit: String
    var tenant: Human? // Opciobalus `Human` stipri nuoroda
    init(unit: String) {
        self.unit = unit
        print("Apartment \(unit) pradedama inicializacija")
    }
    deinit {
        print("Apartment \(unit) baigiasi deinitialization")
    }
}

var john: Human?
var unit4A: Apartment?

john = Human(name: "John Appleseed")
unit4A = Apartment(unit: "4A")

john!.apartment = unit4A
unit4A!.tenant = john

john = nil
unit4A = nil
// Nėra "John Appleseed baigiasi deinitialization" ir "Apartment 4A baigiasi deinitialization" išvesti dėl ciklo stiprių nuorodų

Sprendimas ciklo stiprių nuorodų problemai naudojant weak:

class Human {
    let name: String
    var apartment: Apartment?
    init(name: String) {
        self.name = name
        print("\(name) pradedama inicializacija")
    }
    deinit {
        print("\(name) baigiasi deinitialization")
    }
}

class Apartment {
    let unit: String
    weak var tenant: Human? // Silpna nuoroda
    init(unit: String) {
        self.unit = unit
        print("Apartment \(unit) pradedama inicializacija")
    }
    deinit {
        print("Apartment \(unit) baigiasi deinitialization")
    }
}

var john: Human?
var unit4A: Apartment?

john = Human(name: "John Appleseed")
unit4A = Apartment(unit: "4A")

john!.apartment = unit4A
unit4A!.tenant = john

john = nil // John atlaisvinamas, nes jo nuorodų skaitiklis tampa 0
unit4A = nil // Apartment atlaisvinamas, nes jo nuorodų skaitiklis tampa 0