Dasar-Dasar Pemrograman
Pointer adalah variabel yang menyimpan alamat memori dari variabel lain
int x = 42; // Variabel biasa
int* ptr = &x; // Pointer ke x
Pointer "menunjuk" ke lokasi dimana data disimpan di memori
Memori dapat dibayangkan sebagai deretan kotak dengan alamat unik
int x = 10;
// x disimpan di alamat: 0x7ffd5ba4e8bc
// Kita bisa akses alamat ini dengan pointer
Mendapatkan alamat variabel
int x = 10;
int* ptr = &x;
Akses nilai yang ditunjuk
cout << *ptr; // 10
*ptr = 20; // ubah x
int nilai = 100;
int* ptr = &nilai;
cout << nilai; // 100 (nilai variabel)
cout << &nilai; // 0x... (alamat variabel)
cout << ptr; // 0x... (alamat yang disimpan)
cout << *ptr; // 100 (nilai yang ditunjuk)
int x = 10;
int* ptr = &x;
cout << x; // 10
*ptr = 20; // Ubah x melalui pointer
cout << x; // 20
cout << *ptr; // 20
Pointer dan variabel asli berbagi lokasi memori yang sama!
Nama array adalah pointer konstan ke elemen pertama
int arr[5] = {10, 20, 30, 40, 50};
int* ptr = arr; // arr = &arr[0]
cout << arr; // Alamat arr[0]
cout << ptr; // Sama dengan arr
int arr[5] = {10, 20, 30, 40, 50};
int* ptr = arr;
// Dua cara yang ekuivalen:
cout << arr[0]; // 10
cout << *ptr; // 10
cout << arr[2]; // 30
cout << *(ptr+2); // 30
Operasi aritmatika pada pointer
int arr[5] = {10, 20, 30, 40, 50};
int* ptr = arr; // Menunjuk ke arr[0]
ptr++; // Menunjuk ke arr[1]
cout << *ptr; // 20
cout << *(ptr + 2); // 40 (arr[3])
int arr[5] = {10, 20, 30, 40, 50};
// Menggunakan pointer
int* ptr = arr;
for (int i = 0; i < 5; i++) {
cout << *ptr << " ";
ptr++;
}
// Output: 10 20 30 40 50
void tampilkanArray(int* arr, int ukuran) {
for (int i = 0; i < ukuran; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
int data[5] = {1, 2, 3, 4, 5};
tampilkanArray(data, 5);
int x = 10;
int arr[100];
✓ Otomatis dibersihkan
✓ Cepat
✗ Ukuran tetap
int* x = new int(10);
int* arr = new int[n];
✓ Ukuran fleksibel
✗ Manual management
✗ Lebih lambat
Mengalokasikan memori di heap
// Single variable
int* ptr = new int(42);
// Dengan inisialisasi
double* pi = new double(3.14159);
// Array dinamis
int ukuran = 100;
int* arr = new int[ukuran];
arr[0] = 10; // Gunakan seperti array biasa
Setiap new harus memiliki delete!
// Untuk single variable
int* ptr = new int(42);
// ... gunakan ptr ...
delete ptr;
ptr = nullptr; // Good practice
// Untuk array
int* arr = new int[100];
// ... gunakan arr ...
delete[] arr; // Perhatikan []
arr = nullptr;
int ukuran;
cin >> ukuran;
// Alokasi
int* arr = new int[ukuran];
// Isi array
for (int i = 0; i < ukuran; i++) {
arr[i] = i * 10;
}
// Gunakan array
for (int i = 0; i < ukuran; i++) {
cout << arr[i] << " ";
}
// PENTING: Dealokasi
delete[] arr;
arr = nullptr;
Bahaya: Memori tidak pernah di-dealokasi!
void fungsi() {
int* ptr = new int[1000];
// Gunakan ptr...
// LUPA delete[] ptr; ← MEMORY LEAK!
}
Seiring waktu, program kehabisan memori!
void fungsi() {
int* ptr = new int[1000];
// Gunakan ptr...
delete[] ptr; // PENTING!
ptr = nullptr; // Good practice
}
Selalu pasangkan new dengan delete!
Pointer yang menunjuk ke memori yang sudah dihapus
int* ptr = new int(100);
cout << *ptr; // OK: 100
delete ptr; // Memory freed
// ptr sekarang DANGLING!
cout << *ptr; // DANGER: Undefined behavior!
int* ptr = new int(100);
// ... gunakan ptr ...
delete ptr;
ptr = nullptr; // Set ke null!
// Sekarang aman untuk cek
if (ptr != nullptr) {
cout << *ptr;
} else {
cout << "Pointer null" << endl;
}
// ERROR 1: Uninitialized pointer
int* ptr;
cout << *ptr; // DANGER!
// ERROR 2: Double delete
int* p = new int(42);
delete p;
delete p; // CRASH!
// ERROR 3: delete vs delete[]
int* arr = new int[10];
delete arr; // WRONG!
delete[] arr; // CORRECT!
// ERROR 4: Memory leak
for (int i = 0; i < 1000; i++) {
int* leak = new int[100];
// No delete[]!
}
Pointer yang menyimpan alamat pointer lain
int nilai = 42;
int* ptr1 = &nilai; // Pointer
int** ptr2 = &ptr1; // Pointer ke pointer
cout << nilai; // 42
cout << *ptr1; // 42
cout << **ptr2; // 42
int baris = 3;
int kolom = 4;
// Alokasi matrix
int** matrix = new int*[baris];
for (int i = 0; i < baris; i++) {
matrix[i] = new int[kolom];
}
// Isi matrix
for (int i = 0; i < baris; i++) {
for (int j = 0; j < kolom; j++) {
matrix[i][j] = i * kolom + j;
}
}
// Dealokasi (PENTING: urutan!)
for (int i = 0; i < baris; i++) {
delete[] matrix[i];
}
delete[] matrix;
const int* ptr;
// Bisa ubah pointer
ptr = &x;
ptr = &y;
// Tidak bisa ubah nilai
*ptr = 10; // ERROR
int* const ptr = &x;
// Bisa ubah nilai
*ptr = 10; // OK
// Tidak bisa ubah pointer
ptr = &y; // ERROR
void swap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 5, y = 10;
swap(&x, &y); // Pass alamat
cout << x << " " << y; // 10 5
}
int* ptr = nullptr; // 1. Inisialisasi
if (kondisi) {
ptr = new int[100]; // 2. Alokasi
// 3. Gunakan ptr
ptr[0] = 10;
delete[] ptr; // 4. Dealokasi
ptr = nullptr; // 5. Reset
}
// 6. Cek sebelum gunakan
if (ptr != nullptr) {
cout << *ptr;
}
-fsanitize=address
int* resizeArray(int* old, int oldSize, int newSize) {
int* newArr = new int[newSize];
// Copy data lama
int copySize = min(oldSize, newSize);
for (int i = 0; i < copySize; i++) {
newArr[i] = old[i];
}
// Inisialisasi elemen baru
for (int i = oldSize; i < newSize; i++) {
newArr[i] = 0;
}
delete[] old; // Hapus array lama
return newArr;
}
struct Node {
int data;
Node* next; // Pointer ke node berikutnya
};
void insertAwal(Node** head, int nilai) {
Node* newNode = new Node();
newNode->data = nilai;
newNode->next = *head;
*head = newNode;
}
int x = 10;
int* ptr = &x;
x // Nilai x (10)
&x // Alamat x
ptr // Alamat yang disimpan di ptr (sama dengan &x)
*ptr // Nilai di alamat yang ditunjuk ptr (10)
&ptr // Alamat pointer ptr sendiri
// Modifikasi
*ptr = 20; // Ubah x menjadi 20
ptr++; // Pindah ke memori berikutnya
| Alokasi | Dealokasi |
|---|---|
new Type |
delete ptr |
new Type[size] |
delete[] ptr |
malloc(size) |
free(ptr) |
Jangan mix-and-match! (new dengan free, malloc dengan delete)
Pertanyaan?
Sub-CPMK 3.3: Mahasiswa mampu menerapkan konsep pointer dan penggunaannya dalam program C++