İşaretçi değişkenlerinin kullanımı bir bellek ek yükü değil midir?


29

C ve C ++ gibi dillerde, değişkenleri işaretçiler kullanırken bu adresi saklamak için bir tane daha bellek konumuna ihtiyacımız var. Yani bu bir ek yükü değil mi? Bu nasıl telafi edilir? İşaretçiler zaman kritik düşük bellek uygulamalarında kullanılıyor mu?


11
Dinamik bellek tahsisinin faydaları, işaretçinin maliyetinden çok daha ağır basar.
James McLeod

32
Diğer dillerin (Java, C #, ...) nesnelere referansları nasıl sakladığını düşünüyorsunuz? (İpucu: işaretçiler kullanırlar).
Erik Eidt

6
Bir işaretçi, kayıtlara oturabilir veya bir argüman olarak geçirilebilir. Her iki durumda da ek yükü açık bir bellek yoktur . Ve işaretçi bilgisayarlı olabilir (örn gösterici aritmetiği, işaretçileri dönen fonksiyonlar, vs aracılığıyla)
Basile Starynkevitch

9
Adrese göre (büyük) bir yapı argümanını iletmeye ne dersiniz ? Bunu bir işaretçi değişkeni olarak sayarsanız, birçok algoritma için kaçınılmazdır ve yapıyı değere göre geçirmekten çok daha az alan kullanır !
PJTraill

4
Bu, bazılarının ev ödevi verme hissine sahiptir. Soru, cevabın işaretçileri anlayıp anlamadığını ve nasıl kullanıldığını anlamak için tasarlanmıştır.
Michael Shaw,

Yanıtlar:


34

Aslında, ek yük, işaretçiyi depolamak için gereken fazladan 4 veya 8 bayta gerçektir. Çoğu zaman işaretçiler dinamik bellek ayırma için kullanılır , bu da bir bellek bloğu ayırma işlevini çağırdığımız anlamına gelir ve bu işlev bize bu bellek bloğuna işaret eden bir işaretçi döndürür. Bu yeni blok kendi içinde önemli bir ek yükü temsil ediyor.

Şimdi, yok etmek zorunda Sen bir dizi olabilir: bir işaretçi kullanmak için bellek tahsisi meşgul intstatik veya yığın ilan etti ve ziyaret etmek bir dizin yerine bir işaretçi kullanabilir ints, ve öyle hepsi çok güzel ve basit ve verimli. Bellek ayırmaya gerek yoktur ve işaretçi genellikle bellekte bir tamsayı indeksinin alacağı kadar yer kaplar.

Ayrıca, Joshua Taylor bize bir yorumda hatırlattığında, işaretçiler referans olarak bir şeyleri iletmek için kullanılır. Örneğin, struct foo f; init_foo(&f);yığına f tahsis eder ve init_foo()bunun için bir işaretçi ile çağırır struct. Bu çok yaygın. (Bu işaretçileri "yukarı" geçmemeye dikkat edin.) C ++ 'da foo&bunun bir işaretçi yerine "başvuru" ( ) ile yapıldığını görebilirsiniz , ancak referanslar değiştiremeyeceğiniz işaretçilerden başka bir şey değildir, aynı miktarda hafıza

Ancak, işaretçilerin kullanılmasının temel nedeni dinamik bellek tahsisidir ve bu, başka türlü çözülemeyen sorunları çözmek için yapılır. İşte basit bir örnek: Bir dosyanın tüm içeriğini okumak istediğinizi düşünün. Onları nerede saklayacaksın? Sabit boyutlu bir arabellekle çalışırsanız, o zaman yalnızca bu arabellekten daha uzun olmayan dosyaları okuyabilirsiniz. Ancak, bellek ayırmayı kullanarak dosyayı okumak için gerektiği kadar bellek ayırabilir ve ardından okumaya devam edebilirsiniz.

Ayrıca, C ++ nesne yönelimli bir dildir ve OOP'un sadece işaretçiler kullanılarak elde edilebilecek soyutlama benzeri bazı yönleri vardır . Java ve C # gibi diller bile , işaretçileri kapsamlı şekilde kullanır, yalnızca işaretçileri doğrudan yönlendirmenize izin vermezler; perde arkasında her şeyin işaretçiler kullanılarak yapıldığını fark ettim.

Yani, işaretçileri olan değil sadece zaman açısından kritik, düşük bellek uygulamalarında kullanılan, kullanıldıkları her yerde .


5
"İşaretçilerin kullanılmasının temel nedeni dinamik bellek ayırma içindir" C ++ 'da olabilir, ancak C' de olmayabilir. C 'de, işaretçiler referans alarak bir şeyi iletmenin tek yoludur. Tüm yapıyı kopyalamak istemiyorsanız, bunun için bir işaretçiye ihtiyacınız olacaktır. Hiç dinamik bir tahsisat yapmasanız bile, bu hala mantıklı geliyor. Örneğin, yığında struct foo f; init_foo(&f);tahsis feder ve daha sonra init_foobu yapıya bir işaretçi ile çağırır . Bu çok yaygın. (Bu işaretçileri "yukarı" geçmemeye dikkat edin.)
Joshua Taylor

@JoshuaTaylor bu çok doğru, unutmuştum. Cevabımı değiştirebilir miyim? (Bu, SE programcıları için iyi bir uygulama olarak kabul edilir, çünkü yorumlar geçicidir, cevaplar ise değildir.)
Mike Nakis

Elbette cevabınızı ekleyin. :)
Joshua Taylor,

2
Bu, kendi içinde kayda değer bir yükü temsil eder, çünkü bu blok, genellikle birkaç işaretçi kadar büyük (gizli) bir başlığa sahip olacaktır. => Aslına bakılırsa, modern uygulamalarda mallocblokları "kovalara" kümelendiklerinde ÇOK DÜŞÜK başlığın üst kısmı vardır. Öte yandan, bu genel olarak aşırı tahsisat anlamına gelir: 35 bayt istersiniz ve 64'ünü (bilginiz olmadan) harcarsınız 29 ...
Matthieu M.

1
@MikeNakis: Daha iyi görünüyor, bana sadık kaldığın için teşekkürler :)
Matthieu M.

35

Yani bu bir ek yükü değil mi?

Elbette, fazladan bir adres (işlemciye bağlı olarak genellikle 4/8 bayt).

Bu nasıl telafi edilir?

O değil. İşaretçiler için gerekli olan dolaylı düzenlemeye ihtiyacınız varsa, bunun için para ödersiniz.

İşaretçiler zaman kritik düşük bellek uygulamalarında kullanılıyor mu?

Orada fazla iş yapmadım, ama sanırım öyle. İşaretçi erişimi, montaj programlamanın temel bir özelliğidir. Önemsiz miktarda bellek gerektirir ve bu tür uygulamalar bağlamında bile işaretçi işlemleri hızlıdır.


1
@DavidGrinberg Bu sadece bir dönüş değeri optimizasyonu olmadığını varsayar .
Darkhogg

3
Seksenli yıllarda 15k geri sığması gereken DOS için TSR uygulamaları yazarken işaretçiler kullandım. Yani evet, düşük hafızalı uygulamalarda kullanılırlar.
Robot

1
@StevenBurnap Bir TSR uygulaması için 15k düşük hafızayı mı çağırıyorsunuz? Bir keresinde yalnızca 16 bayt bellek tüketen bir TSR aracı yazdım.
kasperd

22
@ kasperd: Ve günüme dönersek, sadece sıfırımız oldu
Jack


11

Bu konuda Telastyn ile aynı dönüşü yapmadım.

Gömülü bir işlemcideki sistem küreselleri, belirli, kodlanmış adreslerle adreslenebilir.

Bir programdaki küreler, küreler ve statiklerin depolandığı bellekteki yere işaret eden özel bir göstericiden uzaklık olarak ele alınacaktır.

Bir fonksiyon girildiğinde yerel değişkenler görünür ve genellikle "kare işaretçisi" olarak adlandırılan başka bir özel işaretleyiciden ofset olarak adreslenir. Bu, işlevin argümanlarını içerir. Yığın göstergesine basma ve çıkarma konusunda dikkatli olursanız, çerçeve işaretçisiyle uzaklaşabilir ve yerel değişkenlere doğrudan yığın işaretçisinden erişebilirsiniz.

Bu yüzden, bir dizi boyunca sıyrılmaya çalışırken ya da sadece dikkate alınamayan yerel veya küresel bir değişkene sahip olup olmadığınızı işaretçilerin indirilmesi için ödersiniz. Ne tür bir değişken olduğuna bağlı olarak, sadece farklı bir göstergeye dayanıyor. İyi derlenmiş kod, her gösterişinde yeniden yüklemek yerine bu işaretçiyi bir CPU kaydında tutacaktır.


6

Evet tabi ki. Ama bu dengeleyici bir hareket.

İşaretçiler kullanılamaması durumunda, tipik olarak birkaç işaretçi değişkeninin ek yükü ile karşılaştırıldığında, büyük bir programın ne olacağını (hafızada saklanması gereken, unutmayın!) Ek yükü ile kıyaslandığında akılda tutulacak şekilde düşük bellek uygulamaları yapılacaktır. .

Bu düşünce tüm programlar için geçerlidir , çünkü hiç kimse sağ ve ortada bırakılan kopyalanmış kodla korkunç, sürdürülemez bir karışıklık oluşturmak istemez, bu olması gerekenden yirmi kat daha büyüktür.


5

C ve C ++ gibi dillerde, değişkenleri işaretçiler kullanırken bu adresi saklamak için bir tane daha bellek konumuna ihtiyacımız var. Yani bu bir ek yükü değil mi?

İşaretçinin saklanması gerektiğini varsayarsınız. Bu her zaman böyle değildir. Her değişken bir hafıza adresinde saklanır. longOlarak ilan ettiğinizi söyleyin long n = 5L;. Bu n, bazı adreslerde depolamayı ayırır. Bu adresi, *((char *) &n) = (char) 0xFF;parçalarını manipüle etmek gibi süslü şeyler yapmak için kullanabiliriz n. Adresi, nfazladan ek yük olarak hiçbir yere kaydedilmez.

Bu nasıl telafi edilir?

İşaretçiler açıkça depolanmış olsalar da (örneğin, listeler gibi veri yapılarında), elde edilen veri yapısı, işaretçiler olmadan eşdeğer bir veri yapısından daha zarif (daha basit, anlaşılması kolay, kullanımı kolay, vb.).

İşaretçiler zaman kritik düşük bellek uygulamalarında kullanılıyor mu?

Evet. Mikro denetleyicileri kullanan aygıtlar genellikle çok az bellek içerir, ancak bellenim, kesme vektörlerini veya arabellek yönetimini vb. İşlemek için işaretçiler kullanabilir.


Bazı değişkenler hafızada saklanan ancak kayıtlarında değildir
Basile Starynkevitch

@BasileStarynkevitch: Değişkenlerin kayıt defterinde kalmasını önerebilir , ancak derleyici için gerekli değildir. Birleştirme programında programlama yapmazsanız, derhal depolama üzerinde bu düzeyde bir kontrolünüz olmaz. Onun için bunları kullanmak, böylece Ve hatta assembler, sen çağırmak herhangi altyordamı olasılıkla yığının üstüne kayıtlarını akacak onun değişkenleri. Yani önemsiz olmayan herhangi bir program için değişkenlerinizin bellekte en az bir zaman harcayacağına neredeyse garanti edilir.
TMN

Derleyicinin bazı yerel değişkenleri yalnızca yazmaçlarda saklamasına izin verilebilir ve çoğu iyileştirici derleyici bunu yapar ( gcc -fverbose-asm -S -O2bazı C kodlarını derlemeye çalışın )
Basile Starynkevitch

@BasileStarynkevitch Değişkenlerin yalnızca kayıt defterlerinde saklanabileceğini gözlemleyerek yapmaya çalıştığınız noktadan emin değilim. Lütfen detaylandırır mısın?
Lawrence,

5

Bir işaretçiye sahip olmak kesinlikle bazı masrafları tüketir, ancak tersini de görebilirsiniz. İşaretçi dizin gibidir. C'de sadece işaretçilerden dolayı string ve yapılar gibi karmaşık veri yapılarını kullanabilirsiniz.

Aslında, bir değişkeni referansa göre iletmek istediğinizi varsayalım; o zaman tüm yapıyı kopyalamak ve aralarındaki değişiklikleri senkronize etmek yerine bir işaretçiyi bakımı kolaydır (işaretçiyi kopyalamak için bile işaretçiye ihtiyacınız olacaktır). Bitişik olmayan bellek tahsisleri ve işaretçi olmayan tahsisatlarla nasıl başa çıkacaksınız?

Normal değişkenleriniz bile sembol tablosunda, değişkeninizin işaret ettiği adresin bulunduğu bir girişe sahiptir. Bu yüzden hafıza açısından fazla yük oluşturduğunu sanmıyorum (sadece 4 veya 8 bayt). Java gibi diller bile dahili olarak işaretçiler kullanır (başvuru), JVM'yi daha az güvenli hale getireceği için onları değiştirmenize izin vermezler.

İşaretçileri yalnızca eksik veri türleri gibi başka bir seçeneğiniz yoksa, işaretçileri kullanmak (doğru şekilde kullanılmazsa ve hata ayıklamak için nispeten daha zorsa, c (yapıları) gibi yapılar kullanmanız gerekir.


3

Yani bu bir ek yükü değil mi?

Evet Hayır Belki?

Bu çok garip bir soru çünkü makinedeki hafızayı adresleme aralığını ve eşyaların hafızada nerede olduğunu yığına bağlanamayacak şekilde sürekli izlemesi gereken bir yazılım hayal edin.

Örneğin, kullanıcı başka bir müzik dosyası yüklemeye çalıştığında, müzik dosyasının kullanıcı tarafından basılan bir düğmeye yüklendiği ve geçici bellekten çıkarıldığı bir müzik çaları hayal edin.

Ses verilerinin nerede saklandığını nasıl takip ederiz? Bunun için bir hafıza adresine ihtiyacımız var. Programın sadece ses veri yığınını bellekte değil aynı zamanda bellekte bulunduğunu da takip etmesi yeterlidir . Bu nedenle bir hafıza adresini (bir işaretçi gibi) tutmamız gerekir. Bellek adresi için gereken depolamanın boyutu, makinenin adres aralığıyla eşleşecektir (ör: 64 bit adresleme aralığı için 64 bit işaretçi).

Yani bir tür "evet", bir bellek adresini takip etmek için depolama alanı gerektiriyor, ancak bu tür dinamik olarak tahsis edilmiş bellek için önleyemeyeceğimiz bir durum değil.

Bu nasıl telafi edilir?

Bir işaretçinin kendisinin büyüklüğünden bahsedersek, bazı durumlarda yığını kullanarak maliyetlerden kaçınabilirsiniz, örneğin, bu durumda, derleyiciler göreceli bellek adresini etkili bir şekilde kodlayan ve bir işaretçinin maliyetini önleyen talimatlar oluşturabilir. Yine de, eğer bunu büyük, değişken boyutlu tahsisler için yaparsanız, kullanıcı girişi tarafından yönlendirilen karmaşık dallar dizisi için (ses örneğinde olduğu gibi) yapmak için pratik olmama eğiliminde olursunuz. ile elde edilmiş).

Başka bir yol daha bitişik veri yapılarını kullanmaktır. Örneğin, düğüm başına iki işaret gerektiren iki kat bağlı bir liste yerine dizi tabanlı bir sıra kullanılabilir. Bu ikisinin bir melezini, her bir bitişik N elementi grubu arasında sadece işaretçiler depolayan, kontrolsüz bir liste gibi kullanabiliriz.

İşaretçiler zaman kritik düşük bellek uygulamalarında kullanılıyor mu?

Evet, çok yaygın olarak, pek çok performans kritik uygulama işaretçi kullanımının baskın olduğu C ya da C ++ dilinde yazıldığından (bunlar akıllı bir işaretçi ya da kapsayıcısının arkasında olabilir , std::vectorya std::stringda temel mekanikler kullanılan işaretçi için kaynar) adresi dinamik bir hafıza bloğunda takip etmek için).

Şimdi bu soruya dönelim:

Bu nasıl telafi edilir? (Bölüm iki)

İşaretçiler, milyonlarca (örneğin 64 bitlik bir makinede hala yaklaşık olarak 8 megabayt olan) gibi saklamadığınız sürece, genellikle ucuzdurlar.

* Ben'in, "kızarık" 8 megs 'in hala L3 önbellek büyüklüğü olduğuna dikkat çektiğine dikkat edin. Burada “DRAM kullanımı” anlamında daha “ölçülü” kullandım ve bellek parçalarına olan tipik göreceli boyut, işaretçilerin sağlıklı bir şekilde kullanıldığına işaret edecektir.

İşaretçilerin pahalı olduğu yerler işaretçilerin kendileri değildir, ancak:

  1. Dinamik bellek ayırma. Dinamik bellek tahsisi, altta yatan bir veri yapısından geçmesi gerektiği için pahalı olma eğilimindedir (örneğin: dostum veya döşeme tahsisatörü). Bunlar genellikle ölüme göre optimize edilmiş olsalar da, genel amaçlıdırlar ve "arama" 'ya (hafif ve muhtemelen sabit zamanlara rağmen) en az bir miktar iş yapmalarını gerektiren değişken büyüklükteki blokları işlemek için tasarlanmışlardır. bellekte bir dizi bitişik sayfa bulun.

  2. Hafıza erişimi. Bu, endişelenecek en büyük masraf olma eğilimindedir. Dinamik olarak ilk kez tahsis edilen belleğe ne zaman erişirsek, zorunlu bir sayfa hatası olur, ayrıca önbellek bellek hatırası, bellek hiyerarşisinde aşağı ve bir kayıt makinesine taşınır.

Hafıza erişimi

Belleğe erişim, performansın algoritmaların ötesindeki en kritik yönlerinden biridir. AAA oyun motorları gibi performans açısından kritik olan pek çok alan, enerjilerini büyük ölçüde, daha verimli bellek erişim düzenlerine ve düzenlerine kadar kaynayan veri odaklı optimizasyonlara odaklamaktadır.

Her kullanıcı tanımlı türü ayrı bir çöp toplayıcıyla ayrı ayrı tahsis etmek isteyen üst düzey dillerin en büyük performans zorluklarından biri, örneğin belleği biraz parçalayabilmeleridir. Bu, tüm nesnelerin bir kerede tahsis edilmemesi durumunda özellikle geçerli olabilir.

Bu durumlarda, bir kullanıcı tanımlı nesne türünün milyon örneğinin listesini saklarsanız, bu örneklere bir döngü içinde sırayla erişmek oldukça yavaş olabilir, çünkü belleğin farklı bölgelerini işaret eden milyonlarca işaretçi listesine benzemektedir. Bu durumlarda, mimari, büyük, hiyerarşinin daha üst, daha yavaş, daha büyük seviyelerinde bellek biçimini, bu parçalardaki çevreleyen verilere tahliye işleminden önce erişilmesi umuduyla hizalamak ister. Böyle bir listedeki her bir nesneye ayrı ayrı tahsis edildiğinde, çoğu zaman, sonraki her bir yinelemenin, tahliye işleminden önce bitişik nesnelere erişilmeksizin bellekteki tamamen farklı bir alandan yüklenmesi gerekebileceği zaman, önbellek hataları ile ödeme yapıyoruz.

Bu tür diller için derleyicilerin çoğu, bugünlerde talimat seçiminde ve kayıt tahsisinde gerçekten harika bir iş çıkarıyor, ancak burada bellek yönetimi üzerinde daha fazla doğrudan kontrol olmaması, katil olabilir (genellikle daha az hataya eğilimlidir) ve yine de C ve C ++ oldukça popüler.

İşaretçi Erişimini Dolaylı Olarak Optimize Etme

Performans açısından en kritik senaryolarda, uygulamalar genellikle referans konumunu geliştirmek için belleği bitişik parçalardan alan havuzları kullanır. Bu gibi durumlarda, bir ağaç veya bağlantılı bir liste gibi bağlantılı bir yapı bile, düğümlerinin hafıza düzeninin doğada bitişik olması şartıyla önbellek dostu hale getirilebilir. Bu, dolaylı olarak olsa da, başvuruları değiştirirken söz konusu olan referansın konumunu geliştirerek, işaretçi başvuruları daha ucuz hale getirmektedir.

İşaretçiler Etrafında Kovalamak

Tek bir bağlantılı listemiz olduğunu varsayalım:

Foo->Bar->Baz->null

Sorun şu ki, eğer bütün bu düğümleri genel amaçlı bir tahsisatçıya karşı ayrı ayrı tahsis edersek (ve muhtemelen hepsi bir seferde değil), gerçek hafızanın buna benzer bir şekilde dağılmış olması (basitleştirilmiş şema):

görüntü tanımını buraya girin

İşaretçileri kovalamaya ve Foodüğüme erişmeye başladığımızda, bir yığınını bellek bölgesinden daha yavaş bellek bölgelerinden daha hızlı bellek bölgelerine götürmek için zorunlu bir özlemle (ve muhtemelen bir sayfa hatası) başlıyoruz:

görüntü tanımını buraya girin

Bu, yalnızca bir kısmına erişmek için bir bellek bölgesini önbelleğe almamıza (muhtemelen sayfa yapmamıza) ve bu listedeki işaretçileri kovalarken gerisini çıkarmamıza neden olur. Bununla birlikte, bellek ayırıcısı üzerinde kontrolü ele alarak, böyle bir listeyi sürekli olarak şöyle tahsis edebiliriz:

görüntü tanımını buraya girin

... ve böylece, bu işaretçilerden vazgeçme ve işaretçilerini işleme alma hızımızı önemli ölçüde artırır. Dolayısıyla, dolaylı olmasına rağmen, işaretçi erişimini bu şekilde hızlandırabiliriz. Elbette bunları sürekli bir dizide saklarsak, bu konuyu ilk etapta bulamazdık, ancak burada hafıza düzeni üzerinde açık bir kontrol sağlayan bize verilen bellek ayırıcı, bağlantılı bir yapı gerektiğinde günü kurtarabilir.

* Not: Bu, bellek hiyerarşisi ve referansın yeri hakkında çok basitleştirilmiş bir şema ve tartışmadır, ancak umarım sorunun seviyesi için uygundur.


1
"Kızamık 8 megabayt", modern bir CPU'daki L3 önbelleklerin tipik boyutudur
Ben Voigt

1
@BenVoigt Bunu biraz daha küçük düşürmeye çalışacağım. Tabii ki, her bir gösterici 32-bitlik bir bellek

@BenVoigt Bu kısmı netleştirmek için bir dipnot eklendi!

Bu açıklama iyi görünüyor.
Ben Voigt

1

Yani bu bir ek yükü değil mi?

Gerçekten bir yükü, ama çok küçük bir hafızası (önemsiz noktaya kadar).

Bu nasıl telafi edilir?

Tazmin edilmedi. Bir işaretçiyle (işaretçinin işaretini kaldırma) veri erişiminin son derece hızlı olduğunu anlamanız gerekir (doğru hatırlıyorsam, dereference başına yalnızca bir derleme talimatı kullanır). Birçok durumda sahip olabileceğiniz en hızlı alternatif olacak kadar hızlı.

İşaretçiler zaman kritik düşük bellek uygulamalarında kullanılıyor mu?

Evet.


0

Bu işaretçiye ihtiyaç duyurken yalnızca ekstra bellek kullanımına (genellikle işaretçi başına 4-8 bayt) ihtiyacınız vardır. Bunu daha uygun kılan birçok teknik var.

İşaretçileri güçlü yapan en temel teknik, her işaretçiyi tutmanıza gerek kalmamasıdır. Bazen bir işaretçiyi işaretçiden başka bir şeye oluşturmak için bir algoritma kullanabilirsiniz. Bunun en önemsiz örneği dizi aritmetiğidir. Bir 50 tam sayı dizisi ayırırsanız, her bir tam sayı için bir tane 50 işaretçi tutmanıza gerek yoktur. Genellikle bir işaretçiyi (ilkini) izler ve diğerlerini anında oluşturmak için işaretçiyi aritmetik kullanırsınız. Bazen bu işaretçilerden birini dizinin belirli bir öğesinde geçici olarak tutabilirsiniz, ancak yalnızca ihtiyacınız olduğunda. İşiniz bittiğinde, ihtiyaç duyduğunuzda daha sonra yenilenmesi için yeterli bilgiyi sakladığınız sürece, atabilirsiniz. Bu önemsiz görünebilir, ancak bu tam olarak sizin koruma türleriniz

Aşırı dar hafıza durumlarında bu, maliyeti en aza indirmek için kullanılabilir. Eğer bir çalışıyorsanız çok sıkı bellek alanı, genellikle size işlemek gerekir kaç nesneleri iyi bir duygusu var. Bir seferde bir tam sayı tahsis etmek ve onlara tam işaretçiler bırakmak yerine, bu özel algoritmada asla 256'dan fazla tam sayıya sahip olamayacağınız geliştirici bilginizden yararlanabilirsiniz. Bu durumda, ilk tamsayı için bir işaretçi tutabilir ve tam işaretçi (4/8 bayt) kullanmak yerine char (1 bayt) kullanarak bir dizini takip edebilirsiniz. Ayrıca bu endekslerin bir kısmını anında oluşturmak için algoritmik püf noktaları kullanabilirsiniz.

Bu tür bir hafıza vicdanı geçmişte çok popülerdi. Örneğin, NES oyunları, tüm verileri toptan depolamak yerine, verileri toplama ve algoritmalarıyla gösterici üretme yeteneklerine büyük ölçüde güvenecektir.

Aşırı hafıza durumları, derleme zamanında çalıştırdığınız tüm alanları tahsis etmek gibi şeyler yapmaya da yol açabilir. Daha sonra bu belleğe kaydetmeniz gereken işaretçi, verilerden ziyade programda saklanır. Belleğin kısıtlı olduğu birçok durumda, ayrı bir program ve veri belleğiniz vardır (genellikle ROM - RAM gibi), böylece işaretçileri bu program belleğine itmek için algoritmanızı kullanma şeklinizi ayarlayabilirsiniz.

Temel olarak, tüm ek yüklerden kurtulamazsınız. Ancak, kontrol edebilirsiniz. Algoritmik teknikleri kullanarak, depolayabileceğiniz işaretçi sayısını en aza indirebilirsiniz. Dinamik belleğe işaretçiler kullanıyorsanız, bu işaretçiyi bu dinamik bellek noktasında 1 işaretleyiciyi tutma maliyetinin altına düşüremezsiniz, çünkü bu bellek bloğundaki herhangi bir şeye erişmek için gereken minimum bilgi miktarıdır. Bununla birlikte, ultra sıkı bellek kısıtlama senaryolarında, bu özel durum olma eğilimindedir (dinamik bellek ve ultra sıkı bellek kısıtlamaları aynı durumlarda görünme eğilimindedir).


0

Çoğu durumda, işaretçiler hafızada tasarruf sağlar. İşaretçileri kullanmanın yaygın bir alternatifi, veri yapısının bir kopyasını çıkarmaktır. Veri yapısının tam kopyası bir göstergeden daha büyük olacaktır.

Zaman kritik uygulamalara bir örnek bir ağ yığınıdır. İyi bir ağ yığını "sıfır kopya" olarak tasarlanacak ve bunun için işaretçilerin akıllıca kullanılması gerekir.

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.