2013-06-26 17 views
6

Próbuję owinąć moją głowę o void* i jaki jest jej właściwy użytek oraz czy istnieje potencjalne nadużycie, o którym powinienem wiedzieć. (Znaczy coś fajnego, nie jest źle).kiedy używać void * w C++

Nie rozumiem, jak i dlaczego należy korzystać z void*. Jeśli rozumiem, musiałbym rzucić mój aktualny wskaźnik na void*, a następnie powrócić do oryginału, kiedy chciałem go użyć ...?

Dlaczego jest to korzystne? Nie robić rzeczy, generic, bo muszę wiedzieć, jaki rodzaj void* został przekazany zrobić odlew ...

Czy ktoś może mi pomóc zrozumieć void*

+0

C++ zazwyczaj ma lepsze alternatywy, i wiem, że istnieje specyficzny dupek tego, o którym myślę. – chris

+3

W C++ nigdy nie używaj 'void *' oczekiwać w * bardzo * wyjątkowych okolicznościach. –

+1

To jedna z * tych * funkcji. Jeśli nie wiesz, czy go potrzebujesz, nie potrzebujesz go. – delnan

Odpowiedz

6

W C to dość powszechne w użyciu void * stworzyć ogólny zbiór. Na przykład, jeśli chcesz ogólną listę powiązane, można napisać coś takiego:

typedef struct node { 
    void *data; 
    struct node *next; 
} node; 

Następnie można utworzyć jedną połączoną listę foo, innego powiązanego listę bar, i tak dalej.

W języku C++ jest to jednak rzadko przydatne. W typowym przypadku, że chcesz napisać równoważny kod jako szablonu zamiast:

template <typename T> 
class node { 
    T data; 
    node *next; 
}; 

przypadku starszych kompilatorów, można zmniejszyć kod wygenerowany przez połączenie tych dwóch technik. W takim przypadku użyjesz zbioru wskaźników do unieważnienia danych, a następnie szablonowego interfejsu, który po prostu obsłuży odlewanie T * do podczas przechowywania danych iz powrotem od void * do T * po pobraniu dane.

Ulepszenia w kompilatorach/linkerach sprawiły, że ta technika (prawie?) Jest całkowicie przestarzała. Starsze kompilatory generowałyby oddzielny kod dla każdego typu, w którym utworzono twój szablon, nawet gdy typ tworzenia instancji był nieistotny. Bieżące kompilatory (lub w ogóle łańcuchy narzędzi - całkiem sporo z tego jest naprawdę obsługiwane przez linker) identyfikują identyczne sekwencje kodu i łączą je automatycznie.

Konkluzja: chyba trzeba zgodności C, albo piszesz zastępstwo operator new/operator delete, wykorzystanie void * dobrze napisany w C++ jest zwykle dość rzadkie.

+0

Proponuję użyć 'uint8_t *' zamiast 'void *' dla platform, których minimalna adresowalna jednostka to 8-bitów. Moim zdaniem, wskazanie jednostki 8-bitowej jest lepsze niż wskaźnik do niczego. –

1

void* to adres pamięci bez typu. Przydaje się, gdy kod wokół niego ma inny sposób sprawdzenia, z jakim typem on pracuje (na przykład, memchr musi mieć rozmiar obszaru pamięci przekazanego dodatkowo do adresu).