Anatomia i wyjaśnienie wskaźników.

0

Witam. Uczę się jakiś czas c++ i trafiłem na rozdział z wskaźnikami i referencjami. Mógłby mi ktoś wyjaśnić do czego przydają się wskaźniki? Gdzie i jak je stosować? Na przykład taki kod:

// Przykład z DirectX 11.
Co daje ten wskaźnik?

ID3D11Buffer* DebugBufferOutput;

Lub ten?

DataView* dataView = reinterpret_cast<DataView*>(mData.pData);

//Inne
ID3D10Blob* compiledShader = 0;
ID3D10Blob* compilationMsgs = 0;

I ten:

ID3D11Texture2D* backBuffer;
HR(mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer)));
HR(md3dDevice->CreateRenderTargetView(backBuffer, 0, &mRenderTargetView));

A w tej metodzie?

void BFilter::BIPlace(ID3D11DeviceContext* deviceContext){},

Oraz to:

HRESULT D3DX11CreateEffectFromMemory(
void *pData,
ID3D11Device *pDevice,
ID3DX11Effect **ppEffect);

//Wraz z tym
(void**)mRenderCośTam....
co daje (void**)

Czytałem już tutoriale i książki ale jakoś tego nie mogę zajarzyć. Może jak ktoś mi to wytłumaczy na chłopski rozum, to w końcu to zrozumiem. Jeśli ktoś mi to wytłumaczy, wtedy będę ogromnie wdzięczny.

3

Wskaznik to adres do miejsca w pamieci. Wyobraz sobie pamiec. Patrzysz na nia i widzisz jakies bajty:
np. kolejno (w systemie decymalnym): 65,66,67,68,0,....
i teraz jak je zinterpretowac? Nie wiadomo bez informacji o tym co one reprezentuja.

jesli wskaznik jest typu void*, to moga byc jakiekolwiek dane zaczynajace sie na tym adresie, jesli typu int* to prawdopodobnie cztery bajty zaczynajace sie od tego adresu to liczba 1145258561 (lub inna w zaleznosci od endianness i liczby bitow int - chociaz zaklada sie ze int ma 32bity), jesli jest typu void** to jest to prawdopowodbnie czterobajtowy adres do innego miejsca w pamieci ktore nie wiadomo jak zinterpretowac (wskazniki nie musza miec 4 bajtow). Jesli jest typu char* to znaczy ze oznacza to tyle co "ABCD". To w jaki sposob zinterpretowac dane to typ danych. Zmiana w jaki sposob interpretowac miejsce w pamieci to rzutowanie danych (w tym przypadku mowie o reinterpret_cast).

Przykladowo: reinterpret_cast<void**>(&backBuffer)

backBuffer (buffer = blok pamieci) jest prawdopodobnie typu char*, &backBuffer jest typu char** (wskaznik do wskaznika na buffer). Wg. niektorych blok pamieci powinien byc typu void* bo nie dotyczy zadnego konkretnego typu danych, inni uwazaja ze to to samo co tablica bajtow. Oba typy ludzi maja racje. Tak czy siak wskaznik wskazuje na to samo miejsce w pamieci wiec nie pasuje tylko typ dancyh, wiec chcesz go zmienic na to cokolwiek chce biblioteka = uzywasz reinterpret_cast<typ_docelowy>(zmienna_o_typie_wejsciowym).

Generalnie jesli dobrze napiszesz program to wskaznikow powinno byc bardzo malo. Nim bardziej je ukryjesz tym lepiej bo to tylko kolejne miejsce w ktorym latwo popelnic blad. Dlaczego? Dlatego ze wskaznik latwo jest przekonwertowac na liczbe i spowrtotem (czasami moze sie to odbyc bez Twojej wiedzy).

Przykladowo (wydaje mi sie ze da sie zmusic kompilator zeby ponizszy kod sie nie kompilowal, ale nie znam konfiguracji):

int a = 0;
int* liczba = &a;
if (liczba == 0)
{
// costam
}

skompiluje sie, nie wykrzaczy sie, ale nie bedzie dzialac tak jak chciales.

2

Wskaźnik - wskazuje na adres. Zapamiętaj tę jego funkcję.
Jeśli zaalokujemy pamięć dynamicznie to nie ma innego sposobu dostania się do niej, jak tylko przez coś, co wskaże nam jej położenie - wskaźnik. Wskaźnik też może wskazywać na adres jakiejś zmiennej po to, by zmienić sposób interpretowania wartości zawartych w komórkach znajdujących się pod tym adresem.

2

Dodam jeszcze, że jezeli np. stworzysz jakąś klasę, której obiekt będzie zajmował powiedzmy 100MB i będziesz chciał ja przekazać do funkcji przez wartość to program zrobi w tym momencie jej kopie, którą dopiero do funkcji przekaże. Wzrośnie dwukrotnie rozmiar struktury danych. Zamiast tego przekazuje się adres tejże klasy przez wskaźnik albo referencje. Unikasz kopiowania danych i program jest szybszy oraz mniej pamięci zajmuje.

0

Dziękuję wszystkim za odpowiedzi ;) Teraz jako tako rozumiem wskaźniki. Napiszę trochę programów i na pewno zrozumiem je w 100%.

2

Jeszcze możesz tu zerknąć: Gynvael's Code: Pointery #1. Całkiem dobre i szczegółowe wyjaśnienie.

0

Dzięki za link :D

1 użytkowników online, w tym zalogowanych: 0, gości: 1