Swift Academy · Lektion

UnsafePointer og UnsafeMutablePointer

Læs og skriv rå hukommelse omhyggeligt.

Lektion 2 af 413 trin

UnsafePointer og UnsafeMutablePointer er en gratis Swift Academy-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Swift Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Swift Academy-kurset indeholder 4 lektioner i alt.

Typede pointere i Swift

Swifts sikre referencer afslører aldrig rå adresser, men når du arbejder sammen med C eller bygger datastrukturer på lavt niveau, bruger du typede pointere: UnsafePointer<T> til skrivebeskyttet adgang og UnsafeMutablePointer<T> til læsning og skrivning.

En typet pointer kender elementtypen, så den kan beregne afstande og læse en korrekt typet værdi.

// A pointer to an Int we can read but not write
func readFirst(_ p: UnsafePointer<Int>) -> Int {
    return p.pointee
}

Egenskaben pointee

pointee er den værdi, som pointeren i øjeblikket peger på. Med en modificerbar pointer kan du både læse og tildele den; med en skrivebeskyttet pointer kan du kun læse.

Adgang til pointee i uinitialiseret eller deallokeret hukommelse er udefineret adfærd — typesystemet opdager det ikke.

let p = UnsafeMutablePointer<Int>.allocate(capacity: 1)
p.initialize(to: 42)
print(p.pointee)   // 42
p.pointee = 99
print(p.pointee)   // 99

Allokering af hukommelse

UnsafeMutablePointer<T>.allocate(capacity:) reserverer plads til kapacitets elementer, men initialiserer dem ikke. Hukommelsen er rå, og det er ulovligt at læse den før initialisering.

// Reserve space for 3 Doubles (uninitialized)
let buffer = UnsafeMutablePointer<Double>.allocate(capacity: 3)
// Must initialize before reading any element

initialize og deinitialize

Før læsning skal du udføre initialize. Før du deallokerer typer, der kræver oprydning, f.eks. klasser eller strenge, skal du udføre deinitialize for at frigive deres ressourcer.

Livscyklussen er: allocate → initialize → use → deinitialize → deallocate.

let p = UnsafeMutablePointer<String>.allocate(capacity: 1)
p.initialize(to: "hello")
print(p.pointee)
p.deinitialize(count: 1) // releases the String
p.deallocate()

Sæt altid allocate og deallocate i par

Hver allocate skal modsvares af præcis én deallocate, ellers lækker du hukommelse. Det sikreste mønster er at bruge defer lige efter allokeringen, fordi det kører, uanset hvordan funktionen afsluttes.

func process() {
    let p = UnsafeMutablePointer<Int>.allocate(capacity: 1)
    defer { p.deallocate() }
    p.initialize(to: 7)
    print(p.pointee)
} // deallocate runs here automatically

Pointeraritmetik

Typede pointere understøtter indeksering og aritmetik i elementenheder, ikke bytes. p + 2 flytter sig to afstande for T. p[i] er en forkortelse for (p + i).pointee.

let p = UnsafeMutablePointer<Int>.allocate(capacity: 3)
p.initialize(repeating: 0, count: 3)
p[0] = 10
p[1] = 20
p[2] = 30
print((p + 1).pointee) // 20
p.deinitialize(count: 3)
p.deallocate()

initialize for flere elementer

For en hukommelsesblok sætter initialize(repeating:count:) hver plads til den samme værdi, mens initialize(from:count:) kopierer fra en anden buffer. Begge initialiserer hele området, så det er sikkert at læse.

let dst = UnsafeMutablePointer<Int>.allocate(capacity: 4)
dst.initialize(repeating: 5, count: 4)
print(dst[3]) // 5
dst.deinitialize(count: 4)
dst.deallocate()

Skrivebeskyttet kontra modificerbar

En funktion, der kun undersøger data, bør tage UnsafePointer<T>; en funktion, der ændrer dem, bør tage UnsafeMutablePointer<T>. En modificerbar pointer konverteres implicit til en skrivebeskyttet pointer, men ikke omvendt — det håndhæver hensigten ved API-grænsen.

func sum(_ p: UnsafePointer<Int>, _ n: Int) -> Int {
    var total = 0
    for i in 0..<n { total += p[i] }
    return total
}
// A mutable pointer can be passed here directly

withUnsafePointer til lokale værdier

Hvis du vil have en midlertidig pointer til en eksisterende værdi uden at allokere, skal du bruge withUnsafePointer(to:) eller den modificerbare form. Pointeren er kun gyldig i closuren — lad den aldrig slippe ud.

var value = 100
withUnsafeMutablePointer(to: &value) { ptr in
    ptr.pointee += 1
}
print(value) // 101

Almindelige faldgruber

Typede pointere er effektive, men uforsonlige:

  • Læsning af pointee før initialize er udefineret.
  • Hvis du glemmer deinitialize for typer, der indeholder ressourcer, opstår der lækager.
  • Hvis en pointer fra withUnsafePointer slipper ud, får du en hængende pointer.

Her stoler compileren på dig — der er ingen sikkerhedsforanstaltninger under kørsel.

// DANGEROUS — pointer escapes the closure
// var escaped: UnsafePointer<Int>?
// withUnsafePointer(to: &x) { escaped = $0 }
// escaped!.pointee  // dangling, undefined behavior

En lille manuel stak

Hvis vi samler det hele: Allokér en blok, behandl den som elementer ved hjælp af indeksering, og ryd derefter op. Det er grundlaget for brugerdefinerede samlinger og C-integration.

let n = 3
let stack = UnsafeMutablePointer<Int>.allocate(capacity: n)
stack.initialize(repeating: 0, count: n)
for i in 0..<n { stack[i] = i * i }
// stack now holds 0, 1, 4
stack.deinitialize(count: n)
stack.deallocate()

Hurtig kontrol

Husk den korrekte pointer-livscyklus.

Opsamling

Du kender nu typede pointere:

  • UnsafePointer læser, mens UnsafeMutablePointer læser og skriver.
  • pointee giver adgang til værdien; aritmetik foregår i elementenheder.
  • Livscyklussen er allocate → initialize → use → deinitialize → deallocate, helst beskyttet med defer.

Derefter ser du, hvordan bufferpointere indkapsler et helt sammenhængende område i en API, der er egnet til Collection.

Gratis at komme i gang

Lær Swift med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
122
Lektioner
409

Ofte stillede spørgsmål

Er lektionen “UnsafePointer og UnsafeMutablePointer” gratis?

Ja — alle 3 lektioner i læringssporet Swift Academy, inklusive “UnsafePointer og UnsafeMutablePointer”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Swift Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “UnsafePointer og UnsafeMutablePointer”?

Læs og skriv rå hukommelse omhyggeligt. Du øver dig i Swift Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Swift Academy?

Der kræves ingen tidligere erfaring. Swift Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.

Hvor lang tid tager lektionen “UnsafePointer og UnsafeMutablePointer”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Swift Academy-lektion?

Ja. Alle Swift Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. MemoryLayout og alignment
  2. UnsafePointer og UnsafeMutablePointer
  3. Unsafe buffer pointers
  4. withUnsafeBytes og C-interoperabilitet
← Tilbage til Swift Academy