W C++ mamy 4 rodzaje pamięci. Pamięć automatyczna, pamięć dynamiczna, pamięć statyczna oraz pamięć wątku.
Jeśli tworzysz zwykłą zmienną w ten sposób:
int a=5;
To ta zmienna należy do pamięci automatycznej. Cechuję ten rodzaj pamięci to że po wyjściu z bloku kody lub funkcji zmienna ta zostaje automatycznie usuwane. Nie ma to znaczenia czy tworzysz zmienną typu int czy obiekt klasy jeśli robisz to tak jak wyżej.
Zaś jeśli zrobisz tak:
int *a=new int;
*a=5;
To wtedy używasz pamięci dynamicznej. Pamięć ta cechuje się tym że tylko świadome wywołanie polecenia delete zwalnia tą pamięć. Ważne jest tutaj by nie zgubić wskaźnika na komórki pamięci zaalokowane w ten sposób. Jeśli nie zwolnili byśmy tej pamięci to mogło by dojść do wycieku pamięci tzw. Memory Leak.
Tyle wystarczy byś zrozumiał podstawy. Teraz zaś przejdźmy do twojego pytania.
Masz sobie klasę powiedzmy taką;
class Punkt2d
{
public:
int x,y;
};
Jeśli tworzę swój obiekt w ten sposób:
Punkt2d A;
A.x=5;
Czyli korzystam z pamięci automatycznej to jak najbardziej mogę odwoływać się do składowych przez operator kropki.
Jeśli zaś korzystam z tworzenia obiektów w sposób dynamiczny tak jak teraz:
Punkt2d *a=new Punkt2d;
A->x=5;
//pamietaj o zwalnianiu pamieci
delete a;
Jak widzisz korzystam z operatora strzałki (->) a nie jak poprzednio z kropki. Operator strzałki wprowadzono ponieważ wprowadza on pewien porządek.
Jeśli coś jest wskaźnikiem to, jak w naszym przypadku (zmienna a) jest to nic innego jak link prowadzący do adresu w pamięci. Teraz aby dostać się do wartości na jaką wskazuje musimy użyć operatora dereferncji czyli *. W dużym uproszczeniu można by było sądzić, że *a to to samo co A z przykładu o pamięci automatycznej. Oczywiście mówię, że to jest to samo pod względem tym że to są dwa obiekty tej samej klasy nie adres i obiekt. Jeśli jesteśmy już na tym samym poziomie to mogli byśmy teraz użyć operatora kropki.
*a.x=5
Jednak to co jest wyżej nie jest poprawne. Dlaczego zapytasz pewnie ?
Dzieje się tak dlatego że w cpp jest coś takiego jak priorytet operatorów. Operator kropki ma wyższy priorytet od *. Więc najpierw wykona się dostęp do składowej z pomocą kropki a dopiero później dereferencja. Jest to błedne w tym przypadku. Jeśli chcieli byśmy zmienić priorytet operatorów należy użyć nawiasów okrągłych.
(*a).x=5;
a->x=5;
Te dwa zapisu są sobie równoważne.
Na koniec zapraszam cię do przeanalizowania poniższego kodu:
#include <iostream>
using namespace std;
class A
{
public:
int *a;
A()
{
a=new int;
}
~A()
{
delete a;
}
};
int main() {
A z;
*z.a=5;
cout<<z.a<<endl;
cout<<*z.a<<endl;
return 0;
}
Ukazuje on że zapis *z.a=5 jest w pewnych sytuacjach poprawny.