Swift Academy · Pelajaran

UnsafePointer dan UnsafeMutablePointer

Baca dan tulis memori mentah dengan berhati-hati.

Pelajaran 2 daripada 413 langkah

UnsafePointer dan UnsafeMutablePointer ialah pelajaran Swift Academy percuma di CoddyKit. Ini ialah pelajaran 2 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Swift Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Swift Academy merangkumi sejumlah 4 pelajaran.

Penuding Bertip dalam Swift

Rujukan selamat Swift tidak pernah mendedahkan alamat raw, tetapi apabila berinteraksi dengan C atau membina struktur data aras rendah, anda boleh menggunakan penuding bertip: UnsafePointer<T> untuk akses baca sahaja dan UnsafeMutablePointer<T> untuk baca/tulis.

Penuding bertip mengetahui jenis elemen, jadi ia boleh mengira stride dan membaca nilai yang bertip dengan betul.

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

Sifat pointee

pointee ialah nilai yang sedang dituju oleh penuding. Pada penuding boleh ubah, anda boleh membaca dan menetapkan nilainya; pada penuding baca sahaja, anda hanya boleh membacanya.

Mengakses pointee pada memori yang belum dimulakan atau telah dinyahperuntukkan menghasilkan tingkah laku tidak ditakrif — sistem jenis tidak akan mengesannya.

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

Memperuntukkan Memori

UnsafeMutablePointer<T>.allocate(capacity:) menempah ruang untuk capacity elemen tetapi tidak memulakannya. Memori itu masih raw dan membacanya sebelum initialization adalah tidak sah.

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

Initialize dan Deinitialize

Sebelum membaca, anda mesti menggunakan initialize. Sebelum menyahperuntukkan jenis yang memerlukan pembersihan, seperti kelas atau rentetan, anda mesti menggunakan deinitialize untuk melepaskan sumbernya.

Kitar hayatnya ialah: allocate → initialize → gunakan → 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()

Sentiasa Padankan allocate dengan deallocate

Setiap allocate mesti dipadankan tepat dengan satu deallocate, atau anda akan mengalami kebocoran memori. Menggunakan penangguhan sejurus selepas peruntukan ialah corak paling selamat kerana ia dijalankan tanpa mengira cara fungsi berakhir.

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

Aritmetik Penuding

Penuding bertip menyokong pengindeksan dan aritmetik dalam unit elemen, bukan bytes. p + 2 bergerak sebanyak dua stride bagi T. p[i] ialah singkatan bagi (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 Beberapa Elemen

Bagi satu blok memori, initialize(repeating:count:) menetapkan setiap slot kepada nilai yang sama, manakala initialize(from:count:) menyalin daripada penimbal lain. Kedua-duanya memulakan keseluruhan julat, jadi julat itu selamat untuk dibaca.

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

Baca Sahaja berbanding Boleh Diubah

Fungsi yang hanya memeriksa data harus menerima UnsafePointer<T>; fungsi yang mengubahnya menerima UnsafeMutablePointer<T>. Penuding boleh ubah ditukar secara tersirat kepada penuding baca sahaja, tetapi bukan sebaliknya — ini menguatkuasakan tujuan pada sempadan antara muka.

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 untuk Pemboleh Ubah Setempat

Untuk mendapatkan penuding sementara kepada nilai sedia ada tanpa memperuntukkan memori, gunakan withUnsafePointer(to:) atau bentuk boleh ubahnya. Penuding itu sah hanya di dalam penutupan — jangan biarkan penuding itu terlepas.

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

Perangkap Lazim

Penuding bertip berkuasa tetapi tidak bertolak ansur dengan kesilapan:

  • Membaca pointee sebelum initialize menghasilkan tingkah laku tidak ditakrif.
  • Terlupa memanggil deinitialize pada jenis yang menyimpan sumber menyebabkan kebocoran.
  • Membiarkan penuding daripada withUnsafePointer terlepas menghasilkan penuding tergantung.

Pengkompil mempercayai anda dalam hal ini — tiada perlindungan masa jalan.

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

Stack Manual Kecil

Apabila semuanya digabungkan: peruntukkan satu blok, anggapnya sebagai elemen dengan pengindeksan, kemudian lakukan pembersihan. Inilah asas koleksi tersuai dan kesalingoperasian dengan C.

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()

Semak Pantas

Ingat semula kitar hayat penuding yang betul.

Imbas Kembali

Anda kini mengetahui penuding bertip:

  • UnsafePointer membaca, manakala UnsafeMutablePointer membaca dan menulis.
  • pointee mengakses nilai; aritmetik dilakukan dalam unit elemen.
  • Kitar hayatnya ialah allocate → initialize → gunakan → deinitialize → deallocate, sebaik-baiknya dilindungi dengan penangguhan.

Seterusnya, anda akan melihat cara penuding penimbal membungkus seluruh rantau bersebelahan dalam antara muka yang mesra koleksi.

Percuma untuk bermula

Pelajari Swift dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
122
Pelajaran
409

Soalan Lazim

Adakah pelajaran “UnsafePointer dan UnsafeMutablePointer” percuma?

Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Swift Academy, termasuk “UnsafePointer dan UnsafeMutablePointer”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Swift Academy merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “UnsafePointer dan UnsafeMutablePointer”?

Baca dan tulis memori mentah dengan berhati-hati. Anda berlatih Swift Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Swift Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Swift Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 2 daripada 4.

Berapa lamakah pelajaran “UnsafePointer dan UnsafeMutablePointer” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Swift Academy ini?

Ya. Setiap pelajaran Swift Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. MemoryLayout dan Penjajaran
  2. UnsafePointer dan UnsafeMutablePointer
  3. Penuding Penimbal Tidak Selamat
  4. withUnsafeBytes dan Interop C
← Kembali ke Swift Academy