C ++ 'da tanıtıcı nedir?


98

Bir tutamacın bir tür işaretçi olduğu, ancak öyle olmadığı ve nesnenin kendisinden ziyade bir nesneye referans tutmanıza izin verdiği söylendi. Daha ayrıntılı bir açıklama nedir?



2
Sorumluluk Zinciri modeline bakın, "Tanıtıcı" nın temelde bir düğüm olduğunu ve "İşleyicinin" bunlardan küçük bir set olduğunu öğreneceksiniz. "Sihir" özyinelemeden geliyor

Yanıtlar:


101

Bir tutamaç, bir tamsayı indeksinden bir göstericiye, çekirdek uzayındaki bir kaynağa kadar her şey olabilir. Buradaki fikir, bir kaynağın soyutlamasını sağlamasıdır, bu nedenle onu kullanmak için kaynağın kendisi hakkında fazla bir şey bilmenize gerek yoktur.

Örneğin, Win32 API'deki HWND, bir Pencere için bir tanıtıcıdır. Kendi başına işe yaramaz: ondan herhangi bir bilgi toplayamazsınız. Ancak bunu doğru API işlevlerine aktarın ve bununla çok sayıda farklı numara gerçekleştirebilirsiniz. Dahili olarak, HWND'yi sadece GUI'nin pencere tablosuna bir dizin olarak düşünebilirsiniz (bu, nasıl uygulandığı olmayabilir, ancak sihrin mantıklı olmasını sağlar).

DÜZENLEME: Sorunuzda özellikle ne sorduğunuzdan% 100 emin değilim. Bu, esas olarak saf C / C ++ hakkında konuşuyor.


14
Bir Tutamaç, durumları kaydetmek için yararlı olabilir (diğerleri arasında). U std :: vektör gibi bir yapıda veri varsa. Nesneniz, bir programın yürütülmesi sırasında farklı zamanlarda farklı bellek konumlarında olabilir; bu, o belleğe olan işaretçinizin değerleri değiştireceği anlamına gelir. Bir tutamaç ile asla değişmez, daima nesnenize başvurur. Bir programın durumunu kaydetmeyi hayal edin (bir oyunda olduğu gibi) - verilere bir işaretçi konumunu kaydetmezsiniz ve daha sonra verileri tekrar içeri aktarmaz ve bu adresi hafızaya almayı denemeyeceksiniz. Bununla birlikte, verilerinizle bir Tutamaç kaydedebilir ve verileri içe aktarabilir ve işleyebilirsiniz.
SinisterRainbow

Bir HANDLE'ı Linux'taki eşdeğerine dönüştürmek mümkün mü? HANDLE kullanan bir programı Windows'tan Linux'a taşımam gerekiyor.
Cornel Verster

1
Bu doğru cevaptır, herhangi bir şey olabilirler ve bunları kullanan kod, tanıtıcının türünü tanımlar. Gelecek nesil için, kendi benzer cevabımın daha kısa bir versiyonunu yapmaya çalıştım, kendime engel olamadım. @CornelVerster - Linux'ta da aynı. Demek istediğim, işletim sistemi kolları değil, konsept. Bu nedenle, göçü, hatta taşınması gerekliliği konusundaki tutuma bağlıdır.
dyasta

@Matthew Iselin: Herhangi bir API belgesinde, o şeyin bir işleyici olduğunu tanımlıyorlar mı, sonra onları işlevlere
aktarmayı bilmeliyiz

51

Tutamaç, kendisine görünür bir tür eklenmemiş bir işaretçi veya dizindir. Genellikle şöyle bir şey görürsünüz:

 typedef void* HANDLE;
 HANDLE myHandleToSomething = CreateSomething();

Yani kodunuzda sadece HANDLE'ı opak bir değer olarak geçirirsiniz.

Nesneyi kullanan kodda, işaretçiyi gerçek bir yapı tipine çevirir ve kullanır:

 int doSomething(HANDLE s, int a, int b) {
     Something* something = reinterpret_cast<Something*>(s);
     return something->doit(a, b);
 }

Ya da bir dizi / vektöre dizin olarak kullanır:

 int doSomething(HANDLE s, int a, int b) {
     int index = (int)s;
     try {
         Something& something = vecSomething[index];
         return something.doit(a, b);
     } catch (boundscheck& e) {
         throw SomethingException(INVALID_HANDLE);
     }
 }

29

Bir tutamaç , tipik olarak bazı varlıkları referans göstermenin bir yolu olduğu için bir tür işaretçidir.

Bir işaretçinin bir tür tutamaç olduğunu söylemek daha doğru olur, ancak tüm tutamaçlar işaretçi değildir.

Örneğin, bir tutamaç, aynı zamanda, kendisi bir nesneye işaretçi içeren bir girdiye karşılık gelen bir bellek tablosuna bir dizin de olabilir.

Önemli olan, bir "tutamağa" sahip olduğunuzda, bu tutamacın aslında tanımladığı şeyi tanımlayacağını ne bilemezsiniz ne de umursamazsınız, bilmeniz gereken tek şey onun yaptığıdır.

Aynı sistemde bile farklı şeylere yönelik tutamaçlar "başlık altında" farklı şekillerde uygulanabileceğinden, "tam olarak bir tutamaç" ın tek bir cevabı olmadığı da açık olmalıdır. Ancak bu farklılıklarla ilgilenmenize gerek yok.


6

C ++ / CLI'de, bir tutamaç, GC yığınında bulunan bir nesneye bir göstericidir. (Yönetilmeyen) C ++ öbeği üzerinde bir nesnenin oluşturulması kullanılarak elde edilir newve bir newifadenin sonucu "normal" bir göstericidir. Yönetilen bir nesne, bir gcnewifade ile GC (yönetilen) yığınında tahsis edilir . Sonuç bir tutamaç olacaktır. Kollarda işaretçi aritmetiği yapamazsınız. Kolları serbest bırakmıyorsun. GC bunlarla ilgilenecek. Ayrıca, GC yönetilen yığın üzerindeki nesneleri yeniden konumlandırmakta ve program çalışırken yeni konumlara işaret etmek için tutamaçları güncellemek için serbesttir.


5

Bu , aynı zamanda Pimpl deyimi olarak da adlandırılan Handle-Body-Idiom bağlamında ortaya çıkar . Bir kütüphanenin ABI'sini (ikili arabirim), gerçek verileri başka bir sınıf nesnesinde tutarak aynı tutmaya izin verir, bu yalnızca bir "tutamaç" nesnesinde tutulan bir işaretçi tarafından referans alınır, bu sınıfa delege eden işlevlerden oluşur " Vücut".

Aynı zamanda, iki nesnenin sabit zaman ve istisnai güvenli değişimini sağlamak da yararlıdır. Bunun için sadece vücut nesnesine işaret eden işaretçinin değiştirilmesi gerekir.


2

Bir tutamaç, olmasını istediğiniz şeydir.

Bir tutamaç, bazı arama tablolarında kullanılan işaretsiz bir tamsayı olabilir.

Bir tutamaç, daha büyük bir veri kümesine veya bunun içine bir işaretçi olabilir.

Tanıtıcıyı kullanan kodun nasıl davrandığına bağlıdır. Bu, tutamaç tipini belirler.

Önemli olan, ' tutamaç ' teriminin kullanılmasının nedeni . Bu, onları bir kimlik veya erişim türü nesne olarak gösterir. Yani, programcı için bir 'anahtarı' veya bir şeye erişimi temsil ederler .


2

HANDLE hnd; aynıdır void * ptr;

HANDLE, Visual Studio'daki (Windows) winnt.h dosyasında tanımlanan bir typedef'tir:

typedef void *HANDLE;

HANDLE hakkında daha fazla bilgi edinin


1
Bu yalnızca Windows için geçerlidir ve Windows mimarisi aracılığıyla kullanılan birçok türden yalnızca biri. Ancak bu , 'normal Windows uygulama seviyesi tanıtıcısı' olarak bilinen şeydir.
dyasta
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.