Bunu da cevaplayayım.
İşaretçiler referanslara benzer. Başka bir deyişle, bunlar kopya değil, orijinal değere başvurmanın bir yoludur.
Her şeyden önce , tipik olarak çok fazla işaretçi kullanmanız gereken bir yer , gömülü donanımla uğraşırken . Belki bir dijital IO pininin durumunu değiştirmelisiniz. Belki bir kesmeyi işliyorsunuzdur ve belirli bir yerde bir değer depolamanız gerekir. Resmi aldınız. Ancak, donanımla doğrudan ilgilenmiyorsanız ve sadece hangi türlerin kullanılacağını merak ediyorsanız, okumaya devam edin.
Neden normal değişkenlerin aksine işaretçiler kullanılır? Sınıflar, yapılar ve diziler gibi karmaşık türlerle uğraşırken cevap daha açık hale gelir. Normal bir değişken kullanacak olsaydınız, bir kopya oluşturabilirsiniz (derleyiciler bunu önlemek için yeterince akıllıdır ve C ++ 11 de yardımcı olur, ancak şimdilik bu tartışmadan uzak kalacağız).
Orijinal değeri değiştirmek isterseniz ne olur? Bunun gibi bir şey kullanabilirsiniz:
MyType a; //let's ignore what MyType actually is right now.
a = modify(a);
Bu işe yarayacak ve neden işaretçiler kullandığınızı tam olarak bilmiyorsanız, onları kullanmamalısınız. "Muhtemelen daha hızlılar" nedenine dikkat edin. Kendi testlerinizi yapın ve gerçekten daha hızlılarsa bunları kullanın.
Ancak, diyelim ki bellek ayırmanız gereken bir problemi çözüyorsunuz. Belleği ayırdığınızda, yeniden yerleştirmeniz gerekir. Bellek ayırma başarılı olabilir veya olmayabilir. Bu, işaretçilerin yararlı olduğu yerdir - ayırdığınız nesnenin varlığını test etmenize ve işaretçinin referansını alarak belleğin ayrılan nesneye erişmenize izin verir.
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
}
İşaretçileri neden kullanmanızın anahtarı budur - referanslar, başvurduğunuz öğenin zaten var olduğunu varsayar . İşaretçi göstermez.
İşaretçileri kullanmanızın (veya en azından onlarla uğraşmak zorunda kalmanın) diğer bir nedeni, referanslardan önce var olan bir veri türüdür. Bu nedenle, daha iyi olduklarını bildiğiniz şeyleri yapmak için kitaplıklar kullanırsanız, bu kitaplıkların birçoğunun, etrafta ne kadar süredir bulundukları nedeniyle (çok fazla) bunlardan C ++ 'dan önce yazılmıştır).
Herhangi bir kütüphane kullanmadıysanız, kodunuzu işaretçilerden uzak duracak şekilde tasarlayabilirsiniz, ancak işaretçilerin dilin temel türlerinden biri olduğu göz önüne alındığında, bunları ne kadar rahat kullanırsanız, o kadar çok taşınabilir C ++ becerileriniz olurdu.
Sürdürülebilirlik açısından, işaretçileri kullandığınızda, ya geçerliliklerini test etmeniz ve geçerli olmadıklarında davayı ele almanız gerektiğini veya sadece geçerli olduğunu varsaymanız ve varsayım bozulduğunda program çökebilir veya kötüleşir. Başka bir deyişle, işaretçilerle seçiminiz, bir şey bozulduğunda kod karmaşıklığı veya daha fazla bakım çabası getirmektir ve bellek bozulma gibi işaretçilerin getirdiği tüm hata sınıflarına ait bir hatayı izlemeye çalışıyorsunuz.
Bu nedenle, tüm kodunuzu kontrol ederseniz, işaretçilerden uzak durun ve bunun yerine referanslar kullanın, mümkün olduğunda sabit tutun. Bu sizi nesnelerinizin yaşam sürelerini düşünmeye zorlayacak ve kodunuzun daha kolay anlaşılmasını sağlayacaktır.
Sadece bu farkı hatırlayın: Bir referans aslında geçerli bir işaretçi. İşaretçi her zaman geçerli değildir.
Geçersiz bir referans oluşturmanın imkansız olduğunu mu söylüyorum? Hayır. Bu tamamen mümkün, çünkü C ++ neredeyse her şeyi yapmanıza izin veriyor. İstemeden yapmak daha zordur ve kaç tane hatanın istemeden olduğuna şaşıracaksınız :)