Saya baru-baru ini mulai belajar C ++, dan karena kebanyakan orang (sesuai dengan apa yang saya baca) saya berjuang dengan pointer.
Tidak dalam pengertian tradisional, saya mengerti apa itu, dan mengapa mereka digunakan, dan bagaimana mereka bisa berguna, namun saya tidak bisa mengerti bagaimana penambahan pointer akan berguna, adakah yang bisa memberikan penjelasan tentang bagaimana penambahan pointer adalah konsep yang berguna dan C ++ idiomatik?
Pertanyaan ini muncul setelah saya mulai membaca buku A Tour of C ++ oleh Bjarne Stroustrup, saya direkomendasikan buku ini, karena saya cukup akrab dengan Java, dan orang-orang di Reddit mengatakan kepada saya bahwa itu akan menjadi buku 'peralihan' yang baik .
Jawaban:
Ketika Anda memiliki sebuah array, Anda bisa mengatur pointer untuk menunjuk ke elemen array:
Di sini
p
menunjuk ke elemen pertamaa
, yaitua[0]
. Sekarang Anda dapat menambahkan pointer untuk menunjuk ke elemen berikutnya:Sekarang
p
menunjuk ke elemen keduaa[1]
,. Anda dapat mengakses elemen di sini menggunakan*p
. Ini berbeda dari Java di mana Anda harus menggunakan variabel indeks integer untuk mengakses elemen array.Menambah pointer di C ++ di mana pointer itu tidak menunjuk ke elemen array adalah perilaku yang tidak terdefinisi .
sumber
Pointer yang bertambah adalah idiomatik C ++, karena pointer semantik mencerminkan aspek mendasar dari filosofi desain di belakang pustaka standar C ++ (berdasarkan STL Alexander Stepanov )
Konsep penting di sini, adalah bahwa STL dirancang di sekitar wadah, algoritma, dan iterator. Pointer hanyalah iterator .
Tentu saja, kemampuan untuk menambah (atau menambah / mengurangi) pointer kembali ke C. Banyak algoritma manipulasi C-string dapat ditulis hanya dengan menggunakan aritmatika pointer. Pertimbangkan kode berikut:
Kode ini menggunakan pointer aritmatika untuk menyalin string-null yang diakhiri. Loop secara otomatis berakhir ketika bertemu dengan nol.
Dengan C ++, pointer semantik digeneralisasikan ke konsep iterators . Paling standar C ++ wadah memberikan iterator, yang dapat diakses melalui
begin
danend
anggota fungsi. Iterator berperilaku seperti pointer, dalam arti mereka dapat ditingkatkan, dikurangi, dan kadang-kadang dikurangi atau maju.Untuk beralih lebih dari satu
std::string
, kita akan mengatakan:Kami menambah iterator seperti halnya kami akan menambah pointer ke string C-plain. Alasan konsep ini sangat kuat adalah karena Anda dapat menggunakan templat untuk menulis fungsi yang akan bekerja untuk semua jenis iterator yang memenuhi persyaratan konsep yang diperlukan. Dan ini adalah kekuatan STL:
Kode ini menyalin string ke dalam vektor. The
copy
fungsi template yang akan bekerja dengan setiap iterator yang mendukung incrementing (termasuk pointer polos). Kita bisa menggunakancopy
fungsi yang sama pada string C-string:Kita dapat menggunakan
copy
padastd::map
ataustd::set
atau wadah kustom apa pun yang mendukung iterator.Perhatikan bahwa pointer jenis tertentu dari iterator: random akses iterator , yang berarti mereka mendukung incrementing, decrementing, dan maju dengan
+
dan-
operator. Jenis iterator lain hanya mendukung subset dari semantik pointer: iterator dua arah mendukung setidaknya menambah dan mengurangi; a maju iterator mendukung setidaknya incrementing. (Semua jenis iterator mendukung dereferencing.)copy
Fungsi ini membutuhkan iterator yang setidaknya mendukung penambahan.Anda dapat membaca tentang berbagai konsep iterator di sini .
Jadi, incrementing pointer adalah cara C ++ idiomatis untuk beralih pada C-array, atau mengakses elemen / offset dalam C-array.
sumber
Pointer aritmatika berada di C ++ karena berada di C. Aritmatika pointer ada di C karena itu adalah idiom normal dalam assembler .
Ada banyak sistem di mana "register kenaikan" lebih cepat dari "memuat nilai konstan 1 dan menambah mendaftar". Selain itu, beberapa sistem memungkinkan Anda melakukan "muat DWORD ke A dari alamat yang ditentukan dalam register B, lalu tambahkan sizeof (DWORD) ke B" dalam satu instruksi. Saat ini Anda mungkin mengharapkan kompiler pengoptimal untuk menyelesaikan masalah ini untuk Anda, tetapi ini bukan pilihan pada tahun 1973.
Ini pada dasarnya adalah alasan yang sama bahwa array C tidak diperiksa batas dan string C tidak memiliki ukuran yang tertanam di dalamnya: bahasa dikembangkan pada sistem di mana setiap byte dan setiap instruksi dihitung.
sumber