Źle rozumujesz.
Operator new tworzy obiekt w (z naszej perspektywy) losowym miejscu pamięci. Jako wynik zwraca ADRES tego utworzonego obiektu.
Pisząc
_PKT zm;
tworzę obiekt klasy _PKT. Jeżeli napiszę
_PKT * zm1;
utworzę zmienną PRZECHOWUJĄCĄ ADRES do obiektu klasy _PKT. Pisząc
new _PKT;
tworzę obiekt klasy _PKT gdzieś w pamięci. Muszę znać jego ADRES aby coś z nim zrobić. Adres jest wartością tego wyrażenia. Aby więc zapamiętać go w zmiennej zm1 piszę
zm1 =( new _PKT );
. Ale to nie sprawia, że obiekt jest przechowywany jako wartość zmiennej. On jest gdzieś (nie wiem w chwili pisania gdzie) w pamięci. Jeżeli ponownie zapiszę coś w zm1, np.
zm1 = NULL;
lub
zm1 = new _PKT;
to utworzony wcześniej obiekt wcale NIE ZNIKA. Ja tylko nie wiemy gdzie on jest. Gdy przydzielamy pamięć, całe "zaplecze" dba o to, aby zapisać je w miejsce jeszcze nie przydzielone. W końcu więc pamięć się zaśmieci, bo stworzyłem obiekt w pamięci i go porzuciłem. Aby temu zapobiec, należy po sobie sprzątać. Do sprzątania jest operator delete. Gdy napiszę
delete zm1;
, pamięć, na którą WSKAZUJE zm1 zostanie zwolniona i w to miejsce będzie można na nowo przydzielić pamięć operatorem new. To mnie jednak nie ratuje, gdyż straciłem adres pierwszego obiektu, nie mogę więc go ani usunąć, ani czytać/zapisywać. Tak więc ZAŚMIECIŁEM PAMIĘĆ.
Jeżeli napiszę
_PKT * zm1;
_PKT * zm2;
zm1 = new _PKT;
zm2 = zm1;
Stworzę nowy obiekt w pamięci i przypiszę jego adres do zm1, a następnie przepiszę go do zm2. NIE SKOPIOWAŁEM OBIEKTU, tylko jego ADRES. Więc pisząc (zakładamy że punkt ma jedno pole 'int v;')
zm1->v = 12;
, a następnie
cout << zm2->v;
otrzymamy na standardowym wyjściu liczbę
12. A to, dlatego że to TEN SAM obiekt wskazują oba wskaźniki.
Dlatego też napisałem
i = root;
, ponieważ zakładałem, że to tylko kod dodawania elementu do stosu, na którym coś jest.