Pointer ile Fonksiyonlara Parametre Geçirme
Fonksiyonlara adres ile veri aktarma, out parametreler ve maliyet analizi.
C++ dilinde fonksiyonlara parametre gönderirken genellikle değer (by value) veya referans (by reference) aktarımı kullanılır. Ancak bazen bir fonksiyonun doğrudan bellek adresiyle çalışması gerekir — işte bu durumda pointer (gösterici) ile parametre geçirme yöntemi devreye girer. Bu yöntem, değişkenlerin kopyalanmadan doğrudan bellek üzerinden değiştirilmesini sağlar.
1. Değerle ve Pointer ile Parametre Farkı
Fonksiyonlara değerle parametre gönderildiğinde, orijinal değişkenin bir kopyası oluşturulur. Fonksiyon içinde yapılan değişiklikler orijinal değişkeni etkilemez. Pointer ile gönderildiğinde ise fonksiyon doğrudan orijinal belleğe erişir.
#include <iostream>
using namespace std;
void DegeriDegistir(int x) {
x = 20;
}
void PointerIleDegistir(int *p) {
*p = 20;
}
int main() {
int sayi = 10;
DegeriDegistir(sayi);
cout << "Değerle çağırma sonrası: " << sayi << endl; // 10
PointerIleDegistir(&sayi);
cout << "Pointer ile çağırma sonrası: " << sayi << endl; // 20
}
Sonuç: Pointer ile parametre geçirme yöntemi, değişkenin adresi üzerinden doğrudan değerini değiştirebilir.
2. Pointer Parametrelerin Tanımı
Pointer parametreli bir fonksiyon tanımlanırken, parametre türü * işaretiyle belirtilir.
Fonksiyon çağrılırken ise değişkenin adresi & ile gönderilir.
void Degistir(int *ptr) {
*ptr = *ptr + 5;
}
Fonksiyon içinde *ptr ifadesiyle işaret edilen değişkenin gerçek değeri değiştirilir.
Bu yöntem, hem bellek tasarrufu sağlar hem de performansı artırır.
3. Birden Fazla Pointer Parametresi
Aynı anda birden fazla değişken adresi fonksiyona gönderilebilir. Bu yöntem özellikle aritmetik işlemler veya değişken takası (swap) işlemleri için kullanışlıdır.
#include <iostream>
using namespace std;
void DegerleriTakasEt(int *a, int *b) {
int gecici = *a;
*a = *b;
*b = gecici;
}
int main() {
int x = 5, y = 10;
DegerleriTakasEt(&x, &y);
cout << "x: " << x << ", y: " << y << endl; // x:10, y:5
}
Bu örnekte, pointer parametreler sayesinde değişkenlerin bellek adreslerine doğrudan erişilmiştir. Fonksiyon dışındaki değişkenlerin değerleri başarıyla değişmiştir.
4. const Pointer Parametreleri
Eğer bir fonksiyonun parametre olarak aldığı değeri değiştirmemesi gerekiyorsa,
pointer parametresi const olarak tanımlanabilir.
void Yazdir(const int *p) {
cout << "Değer: " << *p << endl;
}
int main() {
int sayi = 42;
Yazdir(&sayi);
}
Bu durumda fonksiyon sadece veriyi okuyabilir, değiştiremez. Bu hem kod güvenliğini artırır hem de yanlışlıkla veri manipülasyonunu önler.
5. Pointer ve Diziler (Array Parametreleri)
C++’ta diziler aslında bir pointer gibi davranır. Bu nedenle diziler fonksiyonlara gönderildiğinde, bellekteki ilk elemanın adresi gönderilir.
void Yazdir(int *dizi, int uzunluk) {
for (int i = 0; i < uzunluk; i++) {
cout << dizi[i] << " ";
}
cout << endl;
}
int main() {
int sayilar[] = {10, 20, 30, 40, 50};
Yazdir(sayilar, 5);
}
Fonksiyon içinde dizi[i] veya *(dizi + i) ifadeleriyle dizinin elemanlarına erişilebilir.
Çünkü dizinin adı, aslında ilk elemanının adresini temsil eder.
6. Pointer ve Dinamik Bellek Parametreleri
Pointer parametreleri, heap üzerinde dinamik olarak oluşturulan verilerle birlikte de kullanılabilir.
#include <iostream>
using namespace std;
void Doldur(int *p, int uzunluk) {
for (int i = 0; i < uzunluk; i++)
p[i] = (i + 1) * 10;
}
int main() {
int *dizi = new int[5]; // Heap'te dinamik dizi
Doldur(dizi, 5);
for (int i = 0; i < 5; i++)
cout << dizi[i] << " ";
delete[] dizi; // Belleği serbest bırak
}
Bu örnekte, pointer parametresi ile heap üzerinde ayrılmış dizinin elemanları doldurulmuştur.
Fonksiyon çağrısından sonra bellek mutlaka delete[] ile serbest bırakılmalıdır.
7. Pointer to Pointer (Çift Pointer)
Pointer’ların kendilerine ait adresleri de tutulabilir. Bu durumda pointer to pointer (çift pointer) kavramı kullanılır. Özellikle fonksiyonun bir pointer’ı değiştirmesi gerektiğinde kullanılır.
void DegistirPointer(int **p) {
static int deger = 99;
*p = °er; // pointer'ın işaret ettiği adresi değiştirir
}
int main() {
int x = 10;
int *ptr = &x;
DegistirPointer(&ptr);
cout << "Yeni değer: " << *ptr << endl; // 99
}
Bu yöntem, fonksiyonun sadece veriyi değil, pointer’ın kendisini de değiştirmesine olanak tanır. Örneğin dinamik bellek yönetimi yapan fonksiyonlarda sıkça kullanılır.
8. Modern C++ Alternatifi: Referanslar ve Smart Pointer’lar
Modern C++ (C++11 ve sonrası) ile birlikte pointer parametrelerin yerini çoğu zaman referanslar veya akıllı pointer’lar (smart pointers) almıştır:
int&→ güvenli, null olamaz, bellek yönetimi gerektirmez.std::unique_ptr→ sahipliği tek bir nesnede tutar.std::shared_ptr→ nesne birden fazla yerde paylaşılabilir.
Ancak düşük seviyeli sistem programlama, gömülü sistemler ve performans kritik uygulamalarda klasik pointer parametreleri hâlâ yaygın olarak kullanılmaktadır.
9. TL;DR
int *p→ pointer parametre tanımıdır;&varile çağrılır.- Pointer parametreleri, fonksiyonların doğrudan belleğe erişmesini sağlar.
const int *p→ sadece okuma amaçlı kullanılır.- Diziler, pointer gibi davranır ve fonksiyonlara adres olarak geçer.
int **p→ pointer to pointer; fonksiyon pointer adresini değiştirebilir.- Modern C++’ta
referencevesmart pointer’lar daha güvenlidir. - Tüm örnekler Visual Studio 2022 veya GCC 11+ derleyicilerinde çalıştırılabilir.