Mengapa menggunakan pointer? [Tutup]

356

Saya tahu ini adalah pertanyaan yang sangat mendasar, tetapi saya baru saja mulai dengan beberapa pemrograman dasar C ++ setelah mengkode beberapa proyek dengan bahasa tingkat tinggi.

Pada dasarnya saya punya tiga pertanyaan:

  1. Mengapa menggunakan pointer di atas variabel normal?
  2. Kapan dan di mana saya harus menggunakan pointer?
  3. Bagaimana Anda menggunakan pointer dengan array?
Kevin
sumber
5
Dibahas sebelumnya pada pertanyaan ini Semoga bermanfaat!
Doug T.
4
Untuk daftar buku, lihat stackoverflow.com/questions/388242/… . Setelah Java, saya menemukan Accelerated C ++ sangat berguna.
Jabba
163
Kami menggunakan petunjuk karena lebih mudah memberi seseorang alamat ke rumah Anda daripada memberikan salinan rumah Anda kepada semua orang.
Rishi Dua
14
@ RishiDua Itulah penjelasan terbaik dari pointer yang pernah saya temui. Terima kasih untuk itu, ini telah meningkatkan pemahaman saya :)
Josh
2
Pointer juga dapat digunakan ketika Anda ingin mengembalikan lebih dari satu nilai / objek.
Gaurav

Jawaban:

172
  • Mengapa menggunakan pointer di atas variabel normal?

Jawaban singkatnya adalah: Jangan. ;-) Pointer harus digunakan di mana Anda tidak dapat menggunakan hal lain. Ini karena kurangnya fungsionalitas yang sesuai, tipe data yang hilang atau untuk kinerja murni. Lebih lanjut di bawah ...

  • Kapan dan di mana saya harus menggunakan pointer?

Jawaban singkat di sini adalah: Di mana Anda tidak dapat menggunakan hal lain. Di C Anda tidak memiliki dukungan untuk tipe data kompleks seperti string. Juga tidak ada cara untuk melewatkan variabel "dengan referensi" ke suatu fungsi. Di situlah Anda harus menggunakan pointer. Anda juga dapat meminta mereka untuk menunjuk hampir apa saja, daftar tertaut, anggota struct dan sebagainya. Tapi mari kita tidak membahasnya di sini.

  • Bagaimana Anda menggunakan pointer dengan array?

Dengan sedikit usaha dan banyak kebingungan. ;-) Jika kita berbicara tentang tipe data sederhana seperti int dan char ada sedikit perbedaan antara array dan pointer. Deklarasi ini sangat mirip (tetapi tidak sama - misalnya, sizeofakan mengembalikan nilai yang berbeda):

char* a = "Hello";
char a[] = "Hello";

Anda dapat menjangkau elemen apa pun dalam array seperti ini

printf("Second char is: %c", a[1]);

Indeks 1 sejak array dimulai dengan elemen 0. :-)

Atau Anda dapat melakukan hal yang sama

printf("Second char is: %c", *(a+1));

Operator penunjuk (*) diperlukan karena kami memberi tahu printf bahwa kami ingin mencetak karakter. Tanpa *, representasi karakter dari alamat memori itu sendiri akan dicetak. Sekarang kita menggunakan karakter itu sendiri. Jika kita menggunakan% s bukannya% c, kita akan meminta printf untuk mencetak konten dari alamat memori yang ditunjukkan oleh 'a' plus satu (dalam contoh di atas), dan kita tidak perlu meletakkan * di depan:

printf("Second char is: %s", (a+1)); /* WRONG */

Tetapi ini tidak hanya akan mencetak karakter kedua, tetapi sebaliknya semua karakter di alamat memori berikutnya, sampai karakter nol (\ 0) ditemukan. Dan di sinilah segalanya mulai menjadi berbahaya. Bagaimana jika Anda secara tidak sengaja mencoba dan mencetak variabel tipe integer alih-alih pointer char dengan formatter% s?

char* a = "Hello";
int b = 120;
printf("Second char is: %s", b);

Ini akan mencetak apa pun yang ditemukan pada alamat memori 120 dan terus mencetak sampai karakter nol ditemukan. Adalah salah dan ilegal untuk melakukan pernyataan printf ini, tetapi mungkin akan tetap berhasil, karena pointer sebenarnya adalah tipe int di banyak lingkungan. Bayangkan masalah yang mungkin Anda sebabkan jika Anda menggunakan sprintf () sebagai gantinya dan menetapkan "char array" terlalu lama ke variabel lain, yang hanya mendapat ruang terbatas tertentu yang dialokasikan. Anda kemungkinan besar akan menulis sesuatu yang lain di memori dan menyebabkan program Anda macet (jika Anda beruntung)

Oh, dan jika Anda tidak menetapkan nilai string ke char array / pointer ketika Anda mendeklarasikannya, Anda HARUS mengalokasikan jumlah memori yang cukup untuk itu sebelum memberikan nilai. Menggunakan malloc, calloc atau sejenisnya. Ini karena Anda hanya mendeklarasikan satu elemen dalam array Anda / satu alamat memori tunggal untuk menunjuk. Jadi, inilah beberapa contoh:

char* x;
/* Allocate 6 bytes of memory for me and point x to the first of them. */
x = (char*) malloc(6);
x[0] = 'H';
x[1] = 'e';
x[2] = 'l';
x[3] = 'l';
x[4] = 'o';
x[5] = '\0';
printf("String \"%s\" at address: %d\n", x, x);
/* Delete the allocation (reservation) of the memory. */
/* The char pointer x is still pointing to this address in memory though! */
free(x);
/* Same as malloc but here the allocated space is filled with null characters!*/
x = (char *) calloc(6, sizeof(x));
x[0] = 'H';
x[1] = 'e';
x[2] = 'l';
x[3] = 'l';
x[4] = 'o';
x[5] = '\0';
printf("String \"%s\" at address: %d\n", x, x);
/* And delete the allocation again... */
free(x);
/* We can set the size at declaration time as well */
char xx[6];
xx[0] = 'H';
xx[1] = 'e';
xx[2] = 'l';
xx[3] = 'l';
xx[4] = 'o';
xx[5] = '\0';
printf("String \"%s\" at address: %d\n", xx, xx);

Perhatikan bahwa Anda masih dapat menggunakan variabel x setelah Anda melakukan bebas () dari memori yang dialokasikan, tetapi Anda tidak tahu apa yang ada di sana. Juga perhatikan bahwa kedua printf () mungkin memberi Anda alamat yang berbeda, karena tidak ada jaminan bahwa alokasi memori kedua dilakukan dalam ruang yang sama dengan yang pertama.

Tooony
sumber
8
Contoh Anda dengan 120 di dalamnya salah. Itu menggunakan% c bukan% s sehingga tidak ada bug; hanya mencetak huruf kecil x. Selain itu, klaim Anda selanjutnya bahwa pointer adalah tipe int adalah salah dan saran yang sangat buruk untuk diberikan kepada seorang programmer C yang tidak berpengalaman dengan pointer.
R .. GitHub BERHENTI MEMBANTU ICE
13
-1 Anda memulai dengan baik tetapi contoh pertama salah. Tidak, tidak sama. Dalam kasus pertama aadalah pointer dan dalam kasus kedua aadalah sebuah array. Apakah saya sudah menyebutkannya? Ini tidak sama! Periksa sendiri: Bandingkan sizeof (a), coba tetapkan alamat baru ke array. Itu tidak akan berhasil.
sellibitze
42
char* a = "Hello";dan char a[] = "Hello";tidak sama, mereka sangat berbeda. Satu menyatakan pointer array yang lain. Coba sizeofdan Anda melihat perbedaannya.
Patrick Schlüter
12
"Tidak salah atau ilegal untuk melakukan pernyataan printf ini". Ini jelas salah. Pernyataan printf itu memiliki perilaku yang tidak jelas. Pada banyak implementasi itu akan menyebabkan pelanggaran akses. Pointer sebenarnya bukan tipe int, mereka sebenarnya pointer (dan tidak ada yang lain).
Mankarse
19
-1, Anda mendapatkan begitu banyak fakta yang salah di sini dan saya hanya akan mengatakan Anda tidak pantas menerima jumlah upvote atau status jawaban yang diterima.
asveikau
50

Salah satu alasan untuk menggunakan pointer adalah agar variabel atau objek dapat dimodifikasi dalam fungsi yang disebut.

Dalam C ++ itu adalah praktik yang lebih baik untuk menggunakan referensi daripada pointer. Meskipun referensi pada dasarnya adalah pointer, C ++ sampai batas tertentu menyembunyikan fakta dan membuatnya seolah-olah Anda melewati nilai. Ini membuatnya mudah untuk mengubah cara fungsi panggilan menerima nilai tanpa harus memodifikasi semantik melewatinya.

Perhatikan contoh-contoh berikut:

Menggunakan referensi:

public void doSomething()
{
    int i = 10;
    doSomethingElse(i);  // passes i by references since doSomethingElse() receives it
                         // by reference, but the syntax makes it appear as if i is passed
                         // by value
}

public void doSomethingElse(int& i)  // receives i as a reference
{
    cout << i << endl;
}

Menggunakan pointer:

public void doSomething()
{
    int i = 10;
    doSomethingElse(&i);
}

public void doSomethingElse(int* i)
{
    cout << *i << endl;
}
trshiv
sumber
16
Mungkin ide yang bagus untuk menyebutkan bahwa referensi lebih aman, karena Anda tidak dapat melewati referensi nol.
SpoonMeiser
26
Ya, itu mungkin keuntungan terbesar menggunakan referensi. Terima kasih telah menunjukkannya. No pun intended :)
trshiv
2
Anda pasti dapat melewati referensi nol. Hanya saja tidak semudah melewati null pointer.
n0rd
1
setuju dengan @ n0rd. Jika Anda pikir Anda tidak dapat melewati referensi nol, Anda salah. Lebih mudah untuk melewatkan referensi yang menggantung daripada referensi nol, tetapi pada akhirnya Anda dapat melakukannya dengan cukup mudah. Referensi bukanlah peluru perak yang melindungi seorang insinyur dari menembak dirinya sendiri di kaki. Lihat itu langsung .
WhozCraig
2
@ n0rd: Melakukan itu adalah perilaku yang secara eksplisit tidak terdefinisi.
Daniel Kamil Kozar
42
  1. Pointer memungkinkan Anda untuk merujuk ke ruang yang sama dalam memori dari berbagai lokasi. Ini berarti Anda dapat memperbarui memori di satu lokasi dan perubahannya dapat dilihat dari lokasi lain di program Anda. Anda juga akan menghemat ruang dengan bisa berbagi komponen dalam struktur data Anda.
  2. Anda harus menggunakan pointer di mana saja di mana Anda perlu mendapatkan dan menyampaikan alamat ke tempat tertentu dalam memori. Anda juga dapat menggunakan pointer untuk menavigasi array:
  3. Array adalah blok memori yang berdekatan yang telah dialokasikan dengan tipe tertentu. Nama array berisi nilai tempat awal array. Ketika Anda menambahkan 1, itu akan membawa Anda ke tempat kedua. Ini memungkinkan Anda untuk menulis loop yang menambah pointer yang slide ke bawah array tanpa memiliki penghitung eksplisit untuk digunakan dalam mengakses array.

Berikut adalah contoh dalam C:

char hello[] = "hello";

char *p = hello;

while (*p)
{
    *p += 1; // increase the character by one

    p += 1; // move to the next spot
}

printf(hello);

cetakan

ifmmp

karena mengambil nilai untuk setiap karakter dan menambahnya dengan satu.

Kyle Cronin
sumber
because it takes the value for each character and increments it by one. Apakah dalam representasi ascii atau bagaimana?
Eduardo S.
28

Pointer adalah salah satu cara untuk mendapatkan referensi tidak langsung ke variabel lain. Alih-alih memegang nilai variabel, mereka memberi tahu Anda alamatnya . Ini sangat berguna ketika berhadapan dengan array, karena menggunakan pointer ke elemen pertama dalam array (alamatnya) Anda dapat dengan cepat menemukan elemen berikutnya dengan menambahkan pointer (ke lokasi alamat berikutnya).

Penjelasan terbaik dari pointer dan aritmatika pointer yang saya baca adalah dalam Bahasa Pemrograman K&R . Buku bagus untuk mulai belajar C ++ adalah C ++ Primer .

Bill the Lizard
sumber
1
Terima kasih! Akhirnya, penjelasan praktis tentang manfaat menggunakan tumpukan! apakah pointer ke posisi dalam array juga meningkatkan kinerja mengakses nilai @ dan relatif ke pointer?
Ini mungkin penjelasan terbaik yang pernah saya baca. orang punya cara "menyulitkan" hal-hal :)
Detailium
23

Biarkan saya mencoba dan menjawab ini juga.

Pointer mirip dengan referensi. Dengan kata lain, itu bukan salinan, melainkan cara untuk merujuk pada nilai asli.

Sebelum hal lain, satu tempat di mana Anda harus sering menggunakan pointer adalah ketika Anda berurusan dengan perangkat keras yang tertanam . Mungkin Anda perlu beralih status pin IO digital. Mungkin Anda sedang memproses interupsi dan perlu menyimpan nilai di lokasi tertentu. Anda mendapatkan fotonya. Namun, jika Anda tidak berurusan dengan perangkat keras secara langsung dan hanya bertanya-tanya tentang jenis yang akan digunakan, baca terus.

Mengapa menggunakan pointer dibandingkan dengan variabel normal? Jawabannya menjadi lebih jelas ketika Anda berurusan dengan tipe kompleks, seperti kelas, struktur, dan array. Jika Anda menggunakan variabel normal, Anda mungkin akhirnya membuat salinan (kompiler cukup pintar untuk mencegah hal ini dalam beberapa situasi dan C ++ 11 juga membantu, tetapi kami akan menjauh dari diskusi itu untuk saat ini).

Sekarang apa yang terjadi jika Anda ingin mengubah nilai asli? Anda dapat menggunakan sesuatu seperti ini:

MyType a; //let's ignore what MyType actually is right now.
a = modify(a); 

Itu akan bekerja dengan baik dan jika Anda tidak tahu persis mengapa Anda menggunakan pointer, Anda tidak harus menggunakannya. Waspadalah terhadap alasan "mereka mungkin lebih cepat". Jalankan tes Anda sendiri dan jika itu sebenarnya lebih cepat, maka gunakanlah.

Namun, katakanlah Anda sedang memecahkan masalah di mana Anda perlu mengalokasikan memori. Ketika Anda mengalokasikan memori, Anda harus membatalkan alokasi itu. Alokasi memori mungkin berhasil atau tidak. Di sinilah pointer berguna - mereka memungkinkan Anda untuk menguji keberadaan objek yang telah Anda alokasikan dan mereka memungkinkan Anda untuk mengakses objek yang dialokasikan memori dengan de-referensi pointer.

MyType *p = NULL; //empty pointer
if(p)
{
    //we never reach here, because the pointer points to nothing
}
//now, let's allocate some memory
p = new MyType[50000];
if(p) //if the memory was allocated, this test will pass
{
    //we can do something with our allocated array
    for(size_t i=0; i!=50000; i++)
    {
        MyType &v = *(p+i); //get a reference to the ith object
        //do something with it
        //...
    }
    delete[] p; //we're done. de-allocate the memory
}

Ini adalah kunci mengapa Anda akan menggunakan pointer - referensi menganggap elemen yang Anda referensi sudah ada . Pointer tidak.

Alasan lain mengapa Anda akan menggunakan pointer (atau setidaknya harus berurusan dengan pointer) adalah karena mereka adalah tipe data yang ada sebelum referensi. Oleh karena itu, jika Anda akhirnya menggunakan perpustakaan untuk melakukan hal-hal yang Anda tahu mereka lebih baik, Anda akan menemukan bahwa banyak perpustakaan ini menggunakan pointer di semua tempat, hanya karena berapa lama mereka sudah ada (banyak dari mereka ditulis sebelum C ++).

Jika Anda tidak menggunakan pustaka apa pun, Anda bisa mendesain kode Anda sedemikian rupa sehingga Anda bisa menjauh dari pointer, tetapi mengingat bahwa pointer adalah salah satu jenis dasar bahasa, semakin cepat Anda merasa nyaman menggunakannya, semakin banyak portabel keterampilan C ++ Anda akan.

Dari sudut pandang rawatan, saya juga harus menyebutkan bahwa ketika Anda menggunakan pointer, Anda harus menguji validitasnya dan menangani kasing ketika tidak valid, atau, anggap saja valid dan terima fakta bahwa Anda Program akan macet atau lebih buruk KAPAN asumsi rusak. Dengan kata lain, pilihan Anda dengan pointer adalah memperkenalkan kompleksitas kode atau upaya pemeliharaan lebih banyak ketika sesuatu rusak dan Anda mencoba melacak bug yang dimiliki seluruh kelas kesalahan yang diperkenalkan pointer, seperti kerusakan memori.

Jadi jika Anda mengontrol semua kode Anda, menjauhlah dari pointer dan alih-alih menggunakan referensi, pertahankan konstanta ketika Anda bisa. Ini akan memaksa Anda untuk berpikir tentang masa hidup objek Anda dan pada akhirnya akan menjaga kode Anda lebih mudah dimengerti.

Hanya ingat perbedaan ini: Referensi pada dasarnya adalah pointer yang valid. Pointer tidak selalu valid.

Jadi, apakah saya mengatakan bahwa tidak mungkin membuat referensi yang tidak valid? Tidak. Ini sangat mungkin, karena C ++ memungkinkan Anda melakukan hampir semua hal. Ini lebih sulit untuk dilakukan tanpa sengaja dan Anda akan kagum pada berapa banyak bug yang tidak disengaja :)

Carl
sumber
Anda dapat menulis kelas pembungkus yang bagus untuk IO yang dipetakan dengan memori yang pada dasarnya Anda dapat menghindari penggunaan pointer.
einpoklum
13

Berikut ini sedikit berbeda, tetapi wawasan mengapa banyak fitur C masuk akal: http://steve.yegge.googlepages.com/tour-de-babel#C

Pada dasarnya, arsitektur CPU standar adalah arsitektur Von Neumann, dan sangat berguna untuk dapat merujuk ke lokasi item data dalam memori, dan melakukan aritmatika dengannya, pada mesin seperti itu. Jika Anda tahu varian bahasa assembly, Anda akan segera melihat betapa pentingnya hal ini di tingkat rendah.

C ++ membuat pointer sedikit membingungkan, karena terkadang mengelola mereka untuk Anda dan menyembunyikan efeknya dalam bentuk "referensi." Jika Anda menggunakan straight C, kebutuhan untuk pointer jauh lebih jelas: tidak ada cara lain untuk melakukan panggilan-oleh-referensi, ini adalah cara terbaik untuk menyimpan string, itu adalah cara terbaik untuk beralih melalui array, dll.

Dan Lenski
sumber
12

Satu penggunaan pointer (saya tidak akan menyebutkan hal-hal yang sudah dibahas dalam posting orang lain) adalah untuk mengakses memori yang belum Anda alokasikan. Ini tidak banyak berguna untuk pemrograman PC, tetapi digunakan dalam pemrograman tertanam untuk mengakses perangkat keras yang dipetakan dengan memori.

Kembali di masa lalu DOS, Anda dulu dapat mengakses memori video kartu video secara langsung dengan mendeklarasikan pointer ke:

unsigned char *pVideoMemory = (unsigned char *)0xA0000000;

Banyak perangkat tertanam masih menggunakan teknik ini.

MrZebra
sumber
Bukan alasan untuk menggunakan pointer - struktur span-like - yang juga memegang panjang - jauh lebih tepat. Sekarang ini gsl::span, dan akan segera tiba std::span.
einpoklum
10

Sebagian besar, pointer adalah array (dalam C / C ++) - mereka adalah alamat dalam memori, dan dapat diakses seperti array jika diinginkan (dalam kasus "normal").

Karena mereka adalah alamat suatu barang, mereka kecil: mereka hanya mengambil ruang alamat. Karena kecil, mengirimnya ke suatu fungsi itu murah. Dan kemudian mereka membiarkan fungsi itu bekerja pada item yang sebenarnya daripada salinan.

Jika Anda ingin melakukan alokasi penyimpanan dinamis (seperti untuk daftar tertaut), Anda harus menggunakan pointer, karena itu satu-satunya cara untuk mengambil memori dari tumpukan.

warren
sumber
8
Saya pikir itu menyesatkan untuk mengatakan pointer adalah array. Sungguh, nama array adalah pointer ke elemen pertama array. Hanya karena Anda dapat mengakses titik arbitrer seolah-olah array tidak berarti itu ... Anda mungkin mendapatkan pelanggaran akses :)
rmeador
2
Pointer bukan array. Baca bagian 6 dari comp.lang.c FAQ .
Keith Thompson
Pointer benar-benar bukan array. Juga, tidak banyak digunakan dalam array mentah juga - tentu saja tidak setelah C ++ 11 dan std::array.
einpoklum
@einpoklum - pointer cukup dekat ke array untuk menjadi setara dalam operasi referensi dan iterasi melalui array :) .... juga - C ++ 11 adalah 3 tahun lagi dari rilis ketika jawaban ini ditulis pada tahun 2008
warren
@warren: Pointer bukan array atau dekat dengan array, mereka hanya meluruh menjadi array. Secara pedagogis tidak pantas untuk memberi tahu orang-orang bahwa mereka serupa. Juga, Anda tentu dapat memiliki referensi ke array, yang bukan tipe yang sama dengan pointer dan mempertahankan informasi ukuran; lihat di sini
einpoklum
9

Pointer penting dalam banyak struktur data yang desainnya membutuhkan kemampuan untuk menghubungkan atau menghubungkan satu "simpul" ke simpul lainnya secara efisien. Anda tidak akan "memilih" pointer daripada mengatakan tipe data normal seperti float, mereka hanya memiliki tujuan berbeda.

Pointer berguna di mana Anda memerlukan kinerja tinggi dan / atau jejak memori kompak.

Alamat elemen pertama dalam array Anda dapat ditetapkan ke sebuah pointer. Ini kemudian memungkinkan Anda untuk mengakses byte yang dialokasikan yang mendasarinya secara langsung. Inti dari array adalah untuk menghindari Anda perlu melakukan ini.

Abu
sumber
9

Salah satu cara untuk menggunakan pointer lebih dari variabel adalah untuk menghilangkan memori duplikat yang diperlukan. Misalnya, jika Anda memiliki beberapa objek kompleks besar, Anda dapat menggunakan pointer untuk menunjuk ke variabel itu untuk setiap referensi yang Anda buat. Dengan variabel, Anda perlu menduplikasi memori untuk setiap salinan.

Jason
sumber
Itu alasan untuk menggunakan referensi (atau paling banyak - pembungkus referensi), bukan pointer.
einpoklum
6

Dalam C ++, jika Anda ingin menggunakan polimorfisme subtipe , Anda harus menggunakan pointer. Lihat posting ini: C ++ Polimorfisme tanpa petunjuk .

Sungguh, ketika Anda memikirkannya, ini masuk akal. Ketika Anda menggunakan subtipe polimorfisme, pada akhirnya, Anda tidak tahu sebelumnya tentang implementasi kelas atau subclass mana dari metode yang akan dipanggil karena Anda tidak tahu apa kelas yang sebenarnya.

Gagasan memiliki variabel yang menyimpan objek dari kelas yang tidak diketahui tidak kompatibel dengan mode default C ++ (non-pointer) untuk menyimpan objek di stack, di mana jumlah ruang yang dialokasikan secara langsung sesuai dengan kelas. Catatan: jika kelas memiliki 5 bidang contoh versus 3, lebih banyak ruang perlu dialokasikan.


Perhatikan bahwa jika Anda menggunakan '&' untuk menyampaikan argumen dengan referensi, tipuan (yaitu, pointer) masih terlibat di belakang layar. Tanda '&' hanyalah gula sintaksis yang (1) menyelamatkan Anda dari masalah menggunakan sintaksis pointer dan (2) memungkinkan kompilator menjadi lebih ketat (seperti melarang null pointer).

Sildoreth
sumber
Tidak, Anda tidak harus menggunakan pointer - Anda dapat menggunakan referensi. Dan ketika Anda menulis "pointer terlibat di belakang layar" - itu tidak ada artinya. gotoinstruksi juga digunakan di belakang layar - dalam instruksi mesin target. Kami masih tidak mengklaim menggunakannya.
einpoklum
@ einpoklum-reinstateMonica Jika Anda memiliki satu set objek yang ingin Anda tindak lanjuti, tetapkan setiap elemen pada gilirannya ke variabel sementara dan memanggil metode polimorfik pada variabel itu, maka ya Anda MEMBUTUHKAN pointer karena Anda tidak dapat mengulang referensi.
Sildoreth
Jika Anda memiliki referensi kelas dasar ke kelas turunan dan memanggil metode virtual pada referensi itu, maka override kelas turunan akan dipanggil. Apakah aku salah?
einpoklum
@ einpoklum-reinstateMonica Itu benar. Tetapi Anda tidak dapat mengubah objek apa yang dirujuk. Jadi, jika Anda mengulang daftar / set / array objek-objek itu, variabel referensi tidak akan berfungsi.
Sildoreth
5

Karena menyalin objek besar di semua tempat menghabiskan waktu dan memori.

tak seorangpun
sumber
4
Dan bagaimana pointer membantu dengan itu? Saya pikir seseorang yang berasal dari Jawa atau. Net tidak tahu perbedaan antara tumpukan dan tumpukan, jadi jawaban ini sangat tidak berguna ..
Mats Fredriksson
Anda dapat melewati referensi. Itu akan mencegah penyalinan.
Martin York
1
@MatsFredriksson - Alih-alih meneruskan (menyalin) struktur data yang besar, dan menyalin hasilnya kembali, Anda hanya menunjuk ke tempatnya di RAM dan kemudian memodifikasinya secara langsung.
John U
Jadi jangan menyalin objek besar. Tidak ada yang mengatakan Anda perlu petunjuk untuk itu.
einpoklum
5

Ini jawaban saya, dan saya tidak ingin menjadi seorang ahli, tetapi saya menemukan petunjuk untuk menjadi hebat di salah satu perpustakaan saya, saya mencoba menulis. Di perpustakaan ini (Ini adalah API grafik dengan OpenGL :-)) Anda dapat membuat segitiga dengan objek verteks diteruskan ke dalamnya. Metode draw mengambil objek segitiga ini, dan well .. menarik mereka berdasarkan objek vertex yang saya buat. Baiklah, tidak apa-apa.

Tapi, bagaimana jika saya mengubah koordinat titik? Memindahkannya atau sesuatu dengan moveX () di kelas vertex? Baiklah, ok, sekarang saya harus memperbarui segitiga, menambahkan lebih banyak metode dan kinerja terbuang karena saya harus memperbarui segitiga setiap kali vertex bergerak. Masih bukan masalah besar, tapi tidak terlalu bagus.

Sekarang, bagaimana jika saya memiliki mesh dengan banyak simpul dan ton segitiga, dan mesh berputar, dan bergerak, dan semacamnya. Saya harus memperbarui setiap segitiga yang menggunakan simpul ini, dan mungkin setiap segitiga dalam adegan karena saya tidak akan tahu mana yang menggunakan simpul mana. Itu sangat intensif komputer, dan jika saya memiliki beberapa jerat di atas lanskap, ya Tuhan! Saya dalam masalah, karena saya memperbarui setiap segitiga hampir setiap frame karena simpul ini berubah setiap saat!

Dengan pointer, Anda tidak perlu memperbarui segitiga.

Jika saya memiliki tiga * objek Vertex per kelas segitiga, tidak hanya saya menghemat ruang karena miliaran segitiga tidak memiliki tiga objek vertex yang besar sendiri, tetapi juga pointer ini akan selalu menunjuk ke Verteks yang seharusnya, tidak peduli seberapa sering simpul berubah. Karena pointer masih menunjuk ke titik yang sama, segitiga tidak berubah, dan proses pembaruan lebih mudah ditangani. Jika saya membingungkan Anda, saya tidak akan meragukannya, saya tidak berpura-pura menjadi ahli, hanya melemparkan dua sen saya ke dalam diskusi.

Jeremy Hahn
sumber
4

Kebutuhan akan pointer dalam bahasa C dijelaskan di sini

Ide dasarnya adalah bahwa banyak batasan dalam bahasa (seperti menggunakan array, string dan memodifikasi beberapa variabel dalam fungsi) dapat dihapus dengan memanipulasi dengan lokasi memori data. Untuk mengatasi keterbatasan ini, petunjuk diperkenalkan di C.

Selanjutnya, juga terlihat bahwa dengan menggunakan pointer, Anda dapat menjalankan kode Anda lebih cepat dan menghemat memori dalam kasus di mana Anda melewati tipe data besar (seperti struktur dengan banyak bidang) ke suatu fungsi. Membuat salinan tipe data seperti itu sebelum lewat akan memakan waktu dan akan menghabiskan memori. Ini adalah alasan lain mengapa programmer lebih suka pointer untuk tipe data besar.

PS: Silakan merujuk tautan yang disediakan untuk penjelasan terperinci dengan kode sampel.

vaibhav kumar
sumber
Pertanyaannya adalah tentang C ++, jawaban ini adalah tentang C.
einpoklum
tidak, pertanyaan ditandai c DAN c ++. Mungkin tag c tidak relevan, tetapi ada di sini sejak awal.
Jean-François Fabre
3

Dalam java dan C # semua referensi objek adalah pointer, masalahnya dengan c ++ adalah bahwa Anda memiliki kontrol lebih besar di mana Anda menunjuk poin. Ingat Dengan kekuatan besar datang tanggung jawab besar.

Marioh
sumber
1

Mengenai pertanyaan kedua Anda, umumnya Anda tidak perlu menggunakan pointer saat pemrograman, namun ada satu pengecualian untuk ini dan saat itulah Anda membuat API publik.

Masalah dengan konstruksi C ++ yang biasanya digunakan orang untuk mengganti pointer sangat bergantung pada toolset yang Anda gunakan yang baik-baik saja ketika Anda memiliki semua kontrol yang Anda butuhkan atas kode sumber, namun jika Anda mengkompilasi perpustakaan statis dengan visual studio 2008 misalnya dan mencoba menggunakannya di visual studio 2010 Anda akan mendapatkan banyak kesalahan penghubung karena proyek baru dikaitkan dengan versi STL yang lebih baru yang tidak kompatibel ke belakang. Hal-hal menjadi lebih nastier jika Anda mengkompilasi DLL dan memberikan pustaka impor yang digunakan orang dalam toolset berbeda karena dalam kasus itu program Anda akan cepat atau lambat crash tanpa alasan yang jelas.

Jadi untuk tujuan memindahkan kumpulan data besar dari satu pustaka ke yang lain, Anda dapat mempertimbangkan untuk memberikan pointer ke array ke fungsi yang seharusnya menyalin data jika Anda tidak ingin memaksa orang lain untuk menggunakan alat yang sama yang Anda gunakan . Bagian yang baik tentang ini adalah bahwa ia bahkan tidak harus menjadi array C-style, Anda dapat menggunakan std :: vector dan memberikan pointer dengan memberikan alamat elemen pertama & vektor [0] misalnya, dan menggunakan std :: vector untuk mengatur array secara internal.

Alasan lain yang baik untuk menggunakan pointer di C ++ lagi berhubungan dengan perpustakaan, pertimbangkan memiliki dll yang tidak dapat dimuat ketika program Anda berjalan, jadi jika Anda menggunakan perpustakaan impor maka ketergantungan tidak terpenuhi dan program macet. Ini terjadi misalnya ketika Anda memberikan api publik di dll bersama aplikasi Anda dan Anda ingin mengaksesnya dari aplikasi lain. Dalam hal ini untuk menggunakan API Anda perlu memuat dll dari lokasinya '(biasanya itu dalam kunci registri) dan kemudian Anda perlu menggunakan pointer fungsi untuk dapat memanggil fungsi di dalam DLL. Terkadang orang yang membuat API cukup baik untuk memberi Anda file .h yang berisi fungsi pembantu untuk mengotomatiskan proses ini dan memberi Anda semua fungsi pointer yang Anda butuhkan,

Radu Chivu
sumber
1
  • Dalam beberapa kasus, pointer fungsi diperlukan untuk menggunakan fungsi yang ada di perpustakaan bersama (.DLL atau .so). Ini termasuk melakukan hal-hal di seluruh bahasa, di mana seringkali antarmuka DLL disediakan.
  • Membuat kompiler
  • Membuat kalkulator ilmiah, di mana Anda memiliki array atau vektor atau peta string pointer fungsi?
  • Mencoba mengubah memori video secara langsung - membuat paket grafik Anda sendiri
  • Membuat API!
  • Struktur data - pointer titik tautan untuk pohon khusus yang Anda buat

Ada banyak alasan untuk pointer. Memiliki nama C mangling terutama penting dalam DLL jika Anda ingin mempertahankan kompatibilitas lintas-bahasa.

Jim Michaels
sumber