Sobes.tech
Middle

Was ist die automatische Linkzählung?

sobes.tech KI

Antwort von AI

Die automatische Referenzzählung (Automatic Reference Counting, ARC) ist ein Speicherverwaltungssystem in Swift und Objective-C, das den Speicher, der Objekten zugewiesen ist, automatisch verfolgt und freigibt. Jede Klasseninstanz hat einen Referenzzähler, der erhöht wird, wenn eine starke Referenz auf das Objekt erstellt wird, und verringert wird, wenn sie entfernt wird. Wenn der Referenzzähler auf null sinkt, deallokiert ARC das Objekt automatisch und gibt den belegten Speicher frei.

ARC verhindert Speicherlecks und doppelte Freigaben, was die Speicherverwaltung im Vergleich zur manuellen Verwaltung (wie in Objective-C ohne ARC) vereinfacht.

Es gibt drei Arten von Referenzen:

  1. Strong (Stark): Erhöht den Referenzzähler des Objekts. Dies ist der Standardreferenztyp.
  2. Weak (Schwach): Erhöht den Referenzzähler nicht. Wird verwendet, um zyklische Referenzen zu verhindern, wenn zwei Objekte sich gegenseitig stark referenzieren. Die schwache Referenz wird nil, wenn das referenzierte Objekt deallokiert wird. Wird mit dem Schlüsselwort weak definiert.
  3. Unowned (Unbesessen): Erhöht den Referenzzähler nicht und hat immer einen Wert. Wird verwendet, wenn bekannt ist, dass die Referenz immer auf ein Objekt zeigt, solange dieses existiert. Im Gegensatz zu weak wird die unbesessene Referenz nicht nil und kann einen Fehler verursachen, wenn versucht wird, auf das Objekt nach dessen Deallokation zuzugreifen. Wird mit dem Schlüsselwort unowned definiert.

Beispiel für einen Zyklus starker Referenzen:

class Human {
    let name: String
    var apartment: Apartment? // Starke Referenz auf ein optionales Apartment
    init(name: String) {
        self.name = name
        print("\(name) wird initialisiert")
    }
    deinit {
        print("\(name) wird deinitialisiert")
    }
}

class Apartment {
    let unit: String
    var tenant: Human? // Starke Referenz auf einen optionalen Human
    init(unit: String) {
        self.unit = unit
        print("Apartment \(unit) wird initialisiert")
    }
    deinit {
        print("Apartment \(unit) wird deinitialisiert")
    }
}

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
// Es wird keine "John Appleseed wird deinitialisiert" oder "Apartment 4A wird deinitialisiert" ausgegeben, aufgrund des Zyklus starker Referenzen

Lösung des Zyklus starker Referenzen mit weak:

class Human {
    let name: String
    var apartment: Apartment?
    init(name: String) {
        self.name = name
        print("\(name) wird initialisiert")
    }
    deinit {
        print("\(name) wird deinitialisiert")
    }
}

class Apartment {
    let unit: String
    weak var tenant: Human? // Schwache Referenz
    init(unit: String) {
        self.unit = unit
        print("Apartment \(unit) wird initialisiert")
    }
    deinit {
        print("Apartment \(unit) wird deinitialisiert")
    }
}

var john: Human?
var unit4A: Apartment?

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

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

john = nil // John wird deallokiert, da sein Referenzzähler 0 ist
unit4A = nil // Apartment wird deallokiert, da sein Referenzzähler 0 ist