İşaretçilerin kullanım durumları ve avantajları nelerdir? [kapalı]


10

Ben sık sık işaretçilerin avantajlarını görmek için mücadele ediyorum (düşük seviye programlama hariç).

Neden bir String veya char [] yerine char * kullanımı ya da pointer aritmeti ne avantajlar getiriyor.

Peki artıları ve kullanım işaretçileri nelerdir?


6
Bu biraz elitist gibi gelecektir, ancak IMHO, işaretçilerin artılarını ve eksilerini sormak zorunda kalırsanız, büyük olasılıkla onlara ihtiyacınız yoktur.
Jas

3
Muhtemelen! Ama soru hala geçerli!
Zolomon

1
Bu aynı zamanda gerçekten dil bilincine sahip değildir, çünkü birçok programlama dilinin C anlamında gerçek göstergeleri yoktur.
David Thornley

Yanıtlar:


6

Dinamik bellek konumu, birçok veri yapısı ve büyük miktarda verinin verimli kullanımı için işaretçiler gereklidir. İşaretçiler olmadan, tüm program verilerini küresel olarak veya işlevler veya eşdeğeri olarak ayırmanız gerekir ve veri miktarı başlangıçta izin verdiğiniz miktarın ötesine ulaşırsa hiçbir başvurunuz olmazdı. Burada mutlak kullanmaktan çekiniyorum, ama bildiğim kadarıyla tüm modern bilgisayar dillerinin bir şekilde işaretçiler var.

İşaretçi kullanan çoğu dilde, işaretçi olan belirli türden referanslar ve belki de olmayan belirli türdeki referanslar vardır ve başka bir gösterimsel fark yoktur. A consbir işaretçi olmasa da Lisp hücresi bir çift işaretleyicidir fixnum. Java'da, sınıf örneği için kullanılan değişken bir işaretçidir, ancak intdeğil. Dil sözdizimi bunu yansıtmaz.

C, işaretçilerin isteğe bağlı, açık ve açık işaretçi aritmetiğine izin vermesi bakımından olağandışıdır. Bu yazma da pekala mümkündür struct foo bar; struct foo * baz;ve hafızayı tahsis ettik kereliğine bazhem kullanabilir barve baztemsil etmek struct foos. İşaretçiler isteğe bağlı olduğundan, gösterimsel farklılıklara sahip olmak yararlıdır. (Bu verildiği gibi, akıllı işaretçiler için C ++ önemlidir boost::shared_ptr<foo> bar;, bar.reset()bir anlamı vardır ve bar->reset()muhtemelen çok daha farklı bir sahip olmaktır.)

(Aslında, ^Pascal'da olduğu gibi C orijinal olarak geliştirilirken açık işaretçiler sıklıkla diğer dillerde kullanılıyordu . C, günümüzde yaygın olarak kullanılanların çoğundan daha eski bir dildir ve gösterir.)

C'nin tasarım hedeflerinden biri Unix'i yazmaktı ve bu nedenle bellek konumlarını ayrıntılı bir şekilde ele almak gerekiyordu. (C aslında tasarlanırken yaygın olan bir sistem uygulama dilleri ailesinden biridir, başka bir örnek ise Kontrol Verisi bilgisayarları için Cybol'dur. C büyük bir hit haline gelmiştir.) Bu nedenle, C işaretleyicilerini doğrudan değiştirmek mümkündür, bellek adresleri atama ve yenilerini hesaplama. Bu aynı zamanda C'deki bazı tasarım kararlarına yol açtı. C dizileri büyük ölçüde işaretçi aritmetiğine dayanır ve aslında bir dizi birçok durumda bir işaretçiye dönüşür. Değişkenlerin C fonksiyonlarına referansla aktarılması işaretçi ile yapılır. Dizilere ve değişkenleri diğer çağdaş dillerin sahip olduğu şeklinde referans alarak güçlü bir ihtiyaç yoktu, bu yüzden C bunları alamadı.

Yani cevap, günümüzde çoğu dilde, hatırlatıcı olmadan sürekli olarak işaretçiler kullanmanızdır. C ve daha az ölçüde C ++ 'da, işaretçileri düşük düzeyli şeyler yapmak veya özel bir gösterim olmayan daha yüksek düzeyli şeyler gerçekleştirmek için kullanırsınız.


çok güzel cevap
Kate Gregory

1
Bu cevabı kabul ediyorum, çünkü C / C ++ 'da işaretçiler ve Java'daki Reference arasında kavrayamadığım farkı en iyi şekilde açıklıyor.
OliverS

Java'nın neden Gosling'in (Java'nın ana yaratıcısı) algılanan "con" unu daha iyi netleştirmek için işaretçiler kullanmadığına dair kısa bir açıklama eklemek iyi olur.
Guido Anselmi

10

Karmaşık veri yapıları. İşaretçiler olmadan bağlantılı liste veya ikili ağaç gibi bir şey oluşturamazsınız.

İşaretçilerin "artıları" ve "eksileri" yoktur. Onlar sadece bir çekiç gibi bir alet.


5
Java'da işaretçi yoktur. Bununla birlikte, bağlantılı liste ve ikili ağaç oluşturmak mümkündür. Referanslar (Java'da olduğu gibi) ve işaretçiler (C'de olduğu gibi) arasında bir fark vardır.
StartClass0830

7
Referanslar ve işaretçiler arasında hiçbir fark yoktur. İşaretçi aritmetiği C'ye özgüdür; işaretçileri olan, ancak işaretçi aritmetiği olmayan (ör. Pascal) başka diller de vardır.
zvrba

1
İşaretçiler ve referanslar düşündüğünüz gibi eş anlamlı değildir. Farklılıkları görmek için bunu okuyun. stackoverflow.com/questions/57483/…
StartClass0830

4
Bu listenin ilk iki öğesini adreslemek için: Java başvuruları yeniden atanabilir ve null değerine işaret edebilirler. Bir işaretçinin ayırt edici özelliği, başka bir nesneye dolaylı olarak başvurmanıza izin vermesidir. Turnusol testim: dairesel veri yapısı oluşturabiliyorsanız (Java referanslarıyla yapabilirsiniz), bu bir göstericidir. (C ++ referanslarıyla dairesel veri yapısı oluşturamayacağınızı unutmayın.)
zvrba

1
İşaretçiler ve referanslar arasında bir fark vardır. Örneğin C # her ikisine de sahiptir . ( blogs.msdn.com/b/ericlippert/archive/2009/02/17/… )
Steven Evers

2
  • İşaretçilerle çalışma zamanında bellek ayırabilir ve yeniden konumlandırabilirsiniz.
  • Ayrıca, izin verilmeyen kapsam dışında büyük veri yapılarını kopyalanmadan kullanabilirsiniz.

C ++, Java ve diğer aynı tür dillerdeki referanslar sadece 'güvenli işaretçilerdir'. Ve bu referanslar Java'da çok kullanılır.


1
C ++ 'da başvurular güvenli işaretçiler DEĞİLDİR. C ++ 'da yapılan referansların işaretçilerle hiçbir ilgisi yoktur. C ++ 'da yapılan başvurular diğer adlardır . Atanamazlar NULLve oluşturulduktan sonra değiştirilemezler.
Billy ONeal

@Billy: C ++ referansları genellikle işaretçiler kullanılarak uygulanır ve bazı şeylerde benzer şekilde çalışır, bu nedenle insanlar bunları bir tür kısıtlanmış işaretçi olarak düşünmeye devam eder.
David Thornley

2

Hemen hemen her bilgisayar programının bellekteki değerleri incelemesi ve değiştirmesi gerekir (gözetleme ve dürtme olarak bilinir, yeterince yaşlı olanlara). Sonuçların tahmin edilebilir olması için bu değerlerin bellekte nerede olduğunu kontrol etmeniz gerekir (ve bazı durumlarda sıra önemlidir: yürütülebilir kodun yüklenmesi bir örnektir). Bu nedenle, bellekteki bir konumu temsil eden bir veri türüne sahip olmanız gerekir. Programlama ortamınız bunu bir soyutlama altında saklasa bile, hala oradadır.


2

char*işaretçiler için crummy bir örnektir. Muhtemelen kullanmaktan daha iyidir std::string(veya unicode / ansi / multibyte özelliğinizi işleyen daha iyi bir tür) char*. İşaretçiler neredeyse diğer Örneğin ( Employee*, PurchaseOrder*, ...), ancak, pek çok avantajı vardır:

  • kapsam tek bir işlevden daha büyük - nesneyi öbek üzerinde tahsis edin ve işaretçiyi uzun süre çevirin
  • daha hızlı işlev, değere göre kopyalama maliyetine sahip olmadığınız için büyük nesneleri çağırır
  • bir işlevin kendisine iletilen parametreleri değiştirmesini sağlamanın bir yolu
  • tüm nesne yerine yalnızca bir adres kopyalayarak koleksiyonlarda yer ve zamandan tasarruf edin

Aslında, işaretçiler o kadar önemlidir ki, görünmeyen çoğu dil aslında sadece onlara sahiptir. C # ve Java'daki referans türleri esasen katı nesneler kılığında işaretçilerdir.

Şimdi, işaretçi manipülasyonu ( p++bir işaretçi üzerinde veya p += delta) bütün bir 'öykü öyküsüdür. Bazı insanlar bunun tehlikeli olduğunu düşünüyor, bazıları bunun harika olduğunu düşünüyor. Ama bu sizin sorunuzdan daha da ileri.


1

İşaretçiler daha hızlı olabilir ve hem veri yapılarında hem de program yürütme ayak izinin düşük tutulmasında daha az ek yüke neden olabilir. (Lütfen 'can' kelimesine dikkat edin.)

Genel kural, eğer kendi tahsisinizi yaparak veya sizin adınıza bir şey yaparak bir kaynak ayırdıysanız, işiniz bittiğinde onu serbest bırakmak sizin görevinizdir.

Yukarıdakileri yapmanın yükü, çalışma zamanının bunu yapmak yerine sorumluluğu geliştiriciye geri vermektir. Bunun, bazı şeylerin daha uzun ömürlü olabilmesi veya sınırları geçebilmesi veya daha uygun zamanlarda atılabilmesi veya bir çöp toplayıcının ağırlığını taşıması gerekmemesi açısından bazı avantajları vardır.

Genellikle istisnalar ve kapsamı içeren egzotik durumlarda, temizleme işleminin kodundan kaçınılması durumunda birinin biraz daha dikkatli olmasını gerektiren bazı kenar durumlar vardır. Gerçekçi olarak, bu durumlar etrafında tasarlanabilir. Uzun yıllardır yönetilen kodlar olmadan yaşadık.

Genellikle işaretçileri “zor” yapan şey, donanım seviyesinde neler olup bittiğini anlamak değildir. Dolaylı olmaktan başka bir şey değildir.

İşaretçiler size çok daha ham erişim sağlar ve bu çok yararlı, zeki veya gerekli olabilir. Herhangi bir yere işaret edebilir ve hemen hemen her şey gibi davranabilirsiniz. Tanrı benzeri güçlerinizi iyilik için kullanırsanız, çok, çok iyidir.

Con tarafı genellikle bir şeyi serbest bırakmayı unutarak veya bir kereden fazla serbest bırakarak veya serbest bırakıldıktan sonra bir şeye başvurarak veya hiçbir yere işaret etmediğinizde bir şeyi reddederek boşa gider. Bunlar genellikle muhteşem çökmelere neden olur ve dürüst olmak gerekirse, işaretçiler kırılgan olmaktan ziyade bir mantık probleminiz olduğunu gösterir.

Sağlam bir geliştiriciyseniz, işaretçileri kullanmak diğer veri yapılarından daha sorunlu olmamalıdır. Yine, bu roket bilimi değil ve insanlar bunu göz kırpmadan onlarca yıldır yaptılar. Bu günlerde daha az içtenlikle öğretildi.

Tüm bunlar, işaretçilere ihtiyacınız olmadığı sürece, iyi bir çöp koleksiyonunun sağladığı taşıma ve dışsal durumlar, yönetilen bir ortamda çalışmayı çok daha güzel hale getirir. Biraz bellek kapmak, kullanmak ve onu terk etmek, bir süre sonra, bunun mantıklı olması durumunda, atılabileceğini bilmek harika. Bu, kodlayıcı tarafında, biraz daha fazla kaldırma yapan bir çalışma zamanı karşılığında biraz daha az kod.


0

En iyi cevap aslında şu soruya dahil edilmiştir: işaretçiler düşük seviyeli programlama içindir. Eğer C kullanıyorsanız, işaretçiler kullanmıyorsanız, bir eliniz arkanıza bağlı olarak programlamaya benzer, ancak bunun cevabı daha üst düzey bir dil kullanmaktır.


-1

İşaretçiler, makineye en ilginç programlama için gereken bir görüş sağlar. Çoğu modern dil cesur bitleri sizden gizler.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.