Powiedziano mi, że uchwyt jest swego rodzaju wskaźnikiem, ale nie, i że pozwala zachować odniesienie do obiektu, a nie do samego obiektu. Jakie jest bardziej szczegółowe wyjaśnienie?
Powiedziano mi, że uchwyt jest swego rodzaju wskaźnikiem, ale nie, i że pozwala zachować odniesienie do obiektu, a nie do samego obiektu. Jakie jest bardziej szczegółowe wyjaśnienie?
Odpowiedzi:
Uchwyt może być czymkolwiek, od indeksu liczb całkowitych do wskaźnika do zasobu w przestrzeni jądra. Chodzi o to, że zapewniają abstrakcję zasobu, więc nie musisz wiedzieć zbyt wiele o samym zasobie, aby z niego korzystać.
Na przykład, HWND w Win32 API jest uchwytem dla okna. Sam w sobie jest bezużyteczny: nie możesz z niego uzyskać żadnych informacji. Ale przekaż go do odpowiednich funkcji API, a możesz z nim wykonać wiele różnych sztuczek. Wewnętrznie możesz myśleć o HWND jako o indeksie tabeli okien GUI (co niekoniecznie musi być tak zaimplementowane, ale sprawia, że magia ma sens).
EDYCJA: Brak 100% pewności, o co konkretnie pytałeś. Mowa tu głównie o czystym C / C ++.
Uchwyt to wskaźnik lub indeks bez dołączonego widocznego typu. Zwykle widzisz coś takiego:
typedef void* HANDLE;
HANDLE myHandleToSomething = CreateSomething();
Więc w swoim kodzie po prostu przekazujesz HANDLE jako nieprzezroczystą wartość.
W kodzie używającym obiektu rzutuje wskaźnik na rzeczywisty typ struktury i używa go:
int doSomething(HANDLE s, int a, int b) {
Something* something = reinterpret_cast<Something*>(s);
return something->doit(a, b);
}
Lub używa go jako indeksu do tablicy / wektora:
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);
}
}
Uchwyt jest rodzajem wskaźnika, ponieważ zazwyczaj jest sposobem odwoływania się do jakiejś jednostki.
Dokładniej byłoby powiedzieć, że wskaźnik jest jednym typem uchwytu, ale nie wszystkie uchwyty są wskaźnikami.
Na przykład uchwyt może być również indeksem do tablicy w pamięci, która odpowiada wpisowi, który sam zawiera wskaźnik do jakiegoś obiektu.
Kluczową sprawą jest to, że kiedy masz „uchwyt”, nie wiesz ani nie obchodzi Cię, w jaki sposób ten uchwyt faktycznie identyfikuje rzecz, którą identyfikuje, wszystko, co musisz wiedzieć, to to, że tak jest.
Powinno też być oczywiste, że nie ma jednej odpowiedzi na pytanie „czym właściwie jest klamka”, ponieważ uchwyty do różnych rzeczy, nawet w tym samym systemie, mogą być realizowane na różne sposoby „pod maską”. Ale nie powinieneś martwić się tymi różnicami.
W C ++ / CLI uchwyt jest wskaźnikiem do obiektu znajdującego się na stercie GC. Utworzenie obiektu na (niezarządzanej) stercie C ++ odbywa się za pomocą, new
a wynikiem new
wyrażenia jest „normalny” wskaźnik. Obiekt zarządzany jest przydzielany na stercie GC (zarządzanej) za pomocą gcnew
wyrażenia. Rezultatem będzie uchwyt. Nie można wykonywać arytmetyki wskaźników na uchwytach. Nie masz wolnych uchwytów. Zaopiekuje się nimi GC. Ponadto GC może przemieszczać obiekty na zarządzanej stercie i aktualizować uchwyty, aby wskazywały nowe lokalizacje, podczas gdy program jest uruchomiony.
Pojawia się to w kontekście idiomu Handle-Body-Idiom , zwanego także idiomem Pimpl. Pozwala na utrzymanie tego samego ABI (binarnego interfejsu) biblioteki, poprzez przechowywanie rzeczywistych danych w innym obiekcie klasy, do którego odwołuje się tylko wskaźnik trzymany w obiekcie "uchwyt", składającym się z funkcji, które są delegowane do tej klasy " Ciało".
Przydatne jest również włączenie stałego czasu i bezpiecznej wymiany dwóch obiektów. W tym celu wystarczy zamienić wskaźnik wskazujący na obiekt ciała.
Uchwyt jest taki, jaki chcesz.
Uchwyt może być liczbą całkowitą bez znaku używaną w jakiejś tabeli przeglądowej.
Uchwyt może być wskaźnikiem do większego zestawu danych lub do niego.
Zależy to od tego, jak zachowuje się kod używający uchwytu. To określa typ uchwytu.
Powód, dla którego używa się terminu „ uchwyt ”, jest ważny. Oznacza to, że są to identyfikatory lub typy dostępu do obiektu. Oznacza to, że dla programisty reprezentują „klucz” lub dostęp do czegoś.
HANDLE hnd;
jest taki sam jak void * ptr;
HANDLE to typedef zdefiniowany w pliku winnt.h w programie Visual Studio (Windows):
typedef void *HANDLE;
Przeczytaj więcej o UCHWYCIE