Thread overview
Pointer ve Referans
Feb 14, 2018
hsencan
Feb 14, 2018
kerdemdemir
Oct 02, 2019
Salih Dinçer
February 14, 2018

Pointer ve referansın ne olduklarını biliyorum. Ama ikisi arasında ki farklar tam olarak nedir ?

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 14, 2018

Pointerlar çok güçlüler ama çok tehlikeliler. Bunu proje çok az büyüsün hemen görebiliyorsun. Bir de hafızadan dinamik olarak(malloc fonksiyonu veya new operatörü )alıp pointer atama yaptıktan sonra eğer pointer'ı silmeyi unutursan "memory leak" oluyor. Eğer bu "update loop" gibi kendini çok tekrar eden bir yerdeyse bir kaç dakka içinde bir bakmışssın hafıza kalmamış oluyor.

Pointerların dezavantaları sıralayacak olursam :

1 - null pointer üzerinden kontrol etmeden ulaşım yapılırsa programımız çöküyor.

A* a = nullptr;
a->foo();//-> Güm

2 - daha da kötüsü silinmiş(belleğe iade edilmiş) fakat null atanmamış bir pointer üzerinden bir fonksiyon çağırdığımızda "undefined behaviour" oluşuyor. En pisi de bu bence keşke patlasada nerde olduğunu anlasak diyor insan.

A* a = new A;
delete a;
a->foo();// Patlayamabilir ama ne yapacağı belli olmaz. İstediğin şeyi yapmıyacağı kesin. Böyle büyük projelerde (bu kadar basit formda değil tabi) çok olur bu didik didik arartırır adama kendini .

3 - Daha da pis bir pointer dezavantajı, pointer aritmetiği.
A* a = new A;
a += 2;// Evet bu yapılabilir çünkü pointerlar kontrolsüz güçlü
a->foo(); // İşte burda yine "undefined behaviour".
Yine tabi pratikde bu kadar basit bir hata kimse yapmıyor ama stackoverflow dediğimiz şey işte bunun türevlerinden oluyor. Sanıyorsam şu 12 yıllık meslek hayatımda aylarca aramışımdır bunlardan.

Şimdi ilk aklıma gelenler bunlar oldu. Böyle şeyler ile ömür tüketen biri olarak artık "new" operatörüne karşı bünyede alerji oluşuyor.

Referanslar eğer mümkünse çok daha güvenli oluyorlar. Eğer mümkünse her zaman pointerlar yerine referanslar kullanılmalı. Bunlar büyülü şeyler değil tabi arka planda pointer'lar ile gerçekleştiriliyorlar fakat işin pis taraflarını derleyice bırakmak çok iyi oluyor.

Referanslar pointerlar kadar esnek değiller. Kullanılmama sebepleri şunlar olabilir.

1 - Bir referansa başlangıç değer atamak zorundayız.

class A
{
int *a; // derlenir
}

class A
{
int& a; // tek başına derlenmez derlenmez
A():a(5) {} // dememiz gerek
}

2 - Pointer 'lara "null" değeri atanıp kullanılabilir. Referanslarda null gibi ekstra bir opsiyon yoktur.

A* foo()
{
bool disktenOkumaHatası = DisktenOku();
if ( disktenOkumaHatası )// işte böyle birşey oldu hayal edelim
return nullptr; // Güzel aslında
return new A();
}

A& foo()
{
bool disktenOkumaHatası = DisktenOku();
if ( disktenOkumaHatası )// işte böyle birşey oldu hayal edelim
// return nullptr; // Böyle bir geri dönüş değeri derlenmez.
throw std::runtime_error("Kötü şeyler oldu");// Artık exception filan uğraşıcaz.
return A();
}

Benim aklıma gelenler bunlar oldu.

Her ikisini kullanırkende oluşabilen dangling pointer/referance durumu olabilir. Dikkat etmek lazım.

Bunun dışında mümkün olduğunca referansları pointerlara tercih etmek lazım.

Erdemdem

Not: Yazmaya başladığımda Ali Abi'nin yazısı yoktu vay arkadaş en az yarım saat yazmışım demekki.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 14, 2018

Arka planda hiçbir fark yok: ikisi de mikroişlemcinin sunduğu "şu adresteki değişkenden bahsetme" olanağını kullanıyorlar. Fark, programlama dili düzeyinde beliriyor.

C++: "Hiçbir şeye referans" olmuyor ama "hiçbir şeyi gösteren gösterge (pointer)" olabiliyor. Farklı söz dizimi kullanıyorlar: 'gösterge->üye' ve 'referans.üye'.

D'de bazı değişkenler referans olamıyor; örneğin, referans üye olamıyor ve referans yerel değişken olamıyor (gösterge kullanmak gerekiyor). D'de söz dizimi aynı 'gösterge.üye' ve 'referans.üye'. (D'de '->' işleci yok.)

D'de sınıf değişkenleri nesne referansları:

   auto değişken = new Sınıf();
   değişken.üye = 42;    // İşlemci düzeyinde gösterge üzerinden erişim

Aklıma gelenler bunlar.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 14, 2018

Söylediklerin doğru ama hemen hemen hepsi referanslar için de geçerli. Fark, kötü duruma düşmek göstergede kolay, referansta zor. D kullanarak gösteriyorum ama aynı durumlar C++'ta da var.

Referans olduğu için güvenip kullanan foo() işlevi yüzünden program çöküyor:

struct S {
   int * p;
   ref i() {
       return *p;
   }
}

// Bence hatasız yazılmış bir işlev:
void foo(ref int i) {
   i = 42;
}

void main() {
   auto s = S();
   foo(s.i);
}

Benzer örnekleri 2 ve 3 numaralı maddeler için de düşünebiliriz.

Evet, açıkça gösterge kullanmak çok daha riskli ama büyük programlarda referanslar da kendilerini kötü durumlarda bulabilirler. :)

D'nin en güzel taraflarından birisi, göstergelere hemen hemen hiç gerek olmuyor... demek istiyorum ama üye ve yerel değişken referans olamadığından oralarda gösterge gerekiyor.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 02, 2019

Konuyla alakalı bir başka başlık:

http://ddili.org/forum/thread/1409

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]