Daftar Isi:
- Lingkup terbatas di C ++
- Mengkaji masalah lingkup di C ++
- Memberikan solusi menggunakan tumpukan di C + +
Video: Heap Sort | GeeksforGeeks 2024
Tumpukan adalah blok memori amorf yang dapat diakses oleh program C ++ Anda. Pelajari tentang mengapa hal itu ada dan bagaimana cara menggunakannya.
Sama seperti mungkin untuk melewatkan sebuah pointer ke sebuah fungsi, ada kemungkinan sebuah fungsi mengembalikan pointer. Fungsi yang mengembalikan alamat ganda dinyatakan sebagai berikut:
double * fn (void);
Namun, Anda harus sangat berhati-hati saat mengembalikan pointer. Untuk memahami bahaya, Anda harus tahu sesuatu tentang ruang lingkup variabel.
Lingkup terbatas di C ++
Ruang lingkup adalah rentang di mana variabel didefinisikan. Perhatikan cuplikan kode berikut:
// variabel berikut dapat diakses ke // semua fungsi dan didefinisikan selama // program berjalan (lingkup global) int intGlobal; // variabel intChild berikut dapat diakses // hanya untuk fungsi dan didefinisikan hanya // asalkan C ++ mengeksekusi fungsi child () atau // yang mana anak () memanggil (scope fungsi) void child (void) {int intChild;} // variabel berikut intParent memiliki fungsi // scope void parent (void) {int intParent = 0; anak(); int intLater = 0; intParent = intLater;} int main (int nArgs, char * pArgs []) {parent ();}
Fragmen program ini dimulai dengan deklarasi variabel intGlobal. Variabel ini ada sejak saat program mulai dijalankan sampai berakhir. Anda mengatakan bahwa intGlobal "memiliki cakupan program. "Anda juga mengatakan bahwa variabel" masuk ke lingkup "bahkan sebelum fungsi utama () dipanggil.
Fungsi utama () segera memanggil orang tua (). Hal pertama yang dilihat prosesor pada orang tua () adalah deklarasi intParent. Pada saat itu, intParent masuk ke dalam lingkup - yaitu, intParent didefinisikan dan tersedia untuk sisa fungsi induk ().
Pernyataan kedua pada orang tua () adalah panggilan untuk anak (). Sekali lagi, fungsi anak () mendeklarasikan variabel lokal, kali ini intChild. Ruang lingkup variabel intChild terbatas pada fungsi anak (). Secara teknis, intParent tidak didefinisikan dalam lingkup anak () karena anak () tidak memiliki akses ke intParent; Namun, variabel intParent terus ada saat anak () sedang mengeksekusi.
Saat anak () keluar, variabel intChild keluar dari ruang lingkup. Tidak hanya intChild yang tidak dapat diakses lagi, sudah tidak ada lagi. (Memori yang diduduki oleh intChild dikembalikan ke kolam umum untuk digunakan untuk hal-hal lain.)
Sebagai orang tua () terus mengeksekusi, variabel intLater masuk ke dalam lingkup deklarasi. Pada titik dimana parent () kembali ke main (), intParent dan intLater keluar dari ruang lingkup.
Karena intGlobal dinyatakan secara global dalam contoh ini, tersedia untuk ketiga fungsi dan tetap tersedia untuk kehidupan program.
Mengkaji masalah lingkup di C ++
Segmen kode berikut dikompilasi tanpa kesalahan namun tidak berhasil (bukankah Anda membenci itu?):
double * child (void) {double dLocalVariable; return & dLocalVariable;} void parent (void) {double * pdLocal; pdLocal = anak (); * pdLocal = 1. 0;}
Masalah dengan fungsi ini adalah bahwa dLocalVariable didefinisikan hanya dalam lingkup fungsi anak (). Jadi, pada saat alamat memori dLocalVariable dikembalikan dari anak (), ini mengacu pada variabel yang sudah tidak ada lagi. Ingatan yang sebelumnya diduduki dLocalVariable mungkin digunakan untuk hal lain.
Kesalahan ini sangat umum karena dapat merayap dalam beberapa cara. Sayangnya, kesalahan ini tidak menyebabkan program berhenti seketika. Sebenarnya, program ini bisa bekerja dengan baik hampir sepanjang waktu - yaitu, program terus berjalan selama memori yang sebelumnya diduduki oleh dLocalVariable tidak segera digunakan kembali. Masalah terputus-putus seperti itulah yang paling sulit dipecahkan.
Memberikan solusi menggunakan tumpukan di C + +
Masalah ruang lingkup berawal karena C ++ mengembalikan memori yang ditetapkan secara lokal sebelum pemrogram siap. Yang dibutuhkan adalah blok memori yang dikendalikan oleh programmer. Dia bisa mengalokasikan memori dan mengembalikannya saat dia ingin - bukan karena C ++ menganggap itu ide bagus. Seperti blok memori disebut tumpukan.
Memori tumpukan dialokasikan menggunakan kata kunci baru diikuti oleh jenis objek yang akan dialokasikan. Perintah baru memecahkan sepotong memori dari tumpukan yang cukup besar untuk menahan jenis objek yang ditentukan dan mengembalikan alamatnya. Sebagai contoh, berikut ini mengalokasikan variabel ganda dari tumpukan:
double * child (void) {double * pdLocalVariable = new double; return pdLocalVariable;}
Fungsi ini sekarang bekerja dengan baik. Meskipun variabel pdLocalVariable keluar dari ruang lingkup ketika fungsi anak () kembali, memori yang menjadi acuan pdLocalVariable tidak. Lokasi memori yang dikembalikan oleh yang baru tidak keluar dari ruang lingkup sampai secara eksplisit dikembalikan ke tumpukan dengan menggunakan kata kunci hapus, yang dirancang khusus untuk tujuan itu:
void parent (void) {// child () mengembalikan alamat dari satu blok // memori tumpukan ganda * pdMyDouble = child (); // simpan nilai di sana * pdMyDouble = 1. 1; // … // sekarang kembalikan memori ke tumpukan hapus pdMyDouble; pdMyDouble = 0; // …}
Disini pointer dikembalikan oleh anak () digunakan untuk menyimpan nilai ganda. Setelah fungsi selesai dengan lokasi memori, maka dikembalikan ke heap. Fungsi parent () mengatur pointer ke 0 setelah memori tumpukan telah dikembalikan - ini bukan persyaratan, tapi ini adalah ide yang sangat bagus.
Jika pemrogram secara keliru mencoba menyimpan sesuatu di * pdMyDouble setelah dihapus, program akan segera mogok dengan pesan kesalahan yang berarti.
Anda bisa menggunakan yang baru untuk mengalokasikan array dari heap juga, tapi Anda harus mengembalikan array menggunakan kata kunci delete []:
int * nArray = new int [10]; nArray [0] = 0; hapus [] nArray;
Secara teknis int baru [10] memanggil operator [] baru namun bekerja sama seperti yang baru.