177
18: ZwyklyKot::ZwyklyKot(int wiek, int waga):
19: jegoWiek(wiek), jegoWaga(waga) (}
20:
21: ZwyklyKot & FunkcjaO;
22:
23: int main()
24: {
25: ZwyklyKot & rKot = FunkcjaO;
26: int wiek = rKot.PobierzWiek();
27: cout « "rKot ma " « wiek « " lat\n";
28: cout « "SrKot: " « SrKot « endl;
29: // Co zrobisz z tą pamięcią?
30: ZwyklyKot * pKot = SrKot;
31: delete pKot;
32: //O jej! rKot wskazuje na ??
33: return 0;
35:
36: ZwyklyKot SFunkcjaO
38: ZwyklyKot * pFrisky = new ZwyklyKot(5,9);
39: cout « "pFrisky: " « pFrisky « endl;
40: return *pFrisky;
pFrisky: 0x2bf4 rKot ma 5 lat SrKot: 0x2bf4
Ten program się kompiluje i pozornie działa. Jednak jest to klasyczna, programistyczna bomba zegarowa z opóźnionym zapłonem!
Funkcja Funkcja () została zmieniona tak, że nie zwraca już referencji
ANALIZA:
do lokalnego obiektu. Teraz pamięć jest rezerwowana na stercie i przypisywana do wskaźnika w linii 38. Adres przechowywany przez wskaźnik jest wypisywany, a następnie są zwracane referencje do obiektu przez niego wskazywanego.
W linii 25, wartość zwracana z funkcji jest przypisywana do referencji obiektu klasy ZwyklyKot. Obiekt ten wykorzystujemy do odczytania wieku kota (linia 26 i 27).
Dowodem na to, że referencja zadeklarowana w main () odnosi się do obiektu stworzonego na stercie jest odczytanie adresu tej referencji. Jest on taki sam jak adres wypisany w funkcji Funkcja ().
Dobrze. Ale jak teraz zwolnić zarezerwowaną pamięć? Nie można skasować referencji za pomocą delete. Jedyne nasuwające się rozwiązanie polega na zadeklarowaniu kolejnego wskaźnika i zainicjowaniu go adresem odczytanym z rKot. W ten sposób możemy zwolnić zarezerwowaną pamięć. Jednak i tu pojawia się kolejny
177
18: ZwyklyKot::ZwyklyKot(int wiek, int waga):
19: jegoWiek(wiek), jegoWaga(waga) ()
20:
21: ZwyklyKot & Funkcja ();
22:
23: int main()
24: (
25: ZwyklyKot & rKot = Funkcja();
26: int wiek = rKot.PobierzWiek();
27: cout « "rKot ma " « wiek « " lat\n";
28: cout « "SrKot: " « SrKot « endl;
29: // Co zrobisz z tą pamięcią?
30: ZwyklyKot * pKot = SrKot;
31: delete pKot;
32: // O jej! rKot wskazuje na ??
33: return 0;
35:
36: ZwyklyKot SFunkcjaf)
38: ZwyklyKot * pFrisky = new ZwyklyKot(5,9);
39: cout « "pFrisky: " « pFrisky « endl;
40: return ‘pFrisky;
pFrisky: 0x2bf4 rKot ma 5 lat SrKot: 0x2bf4
Funkcja Funkcja () została zmieniona tak, że nie zwraca już referencji do lokalnego obiektu. Teraz pamięć jest rezerwowana na stercie i przypisywana do wskaźnika w linii 38. Adres przechowywany przez wskaźnik jest wypisywany, a następnie są zwracane referencje do obiektu przez niego wskazywanego.
W linii 25, wartość zwracana z funkcji jest przypisywana do referencji obiektu klasy ZwyklyKot. Obiekt ten wykorzystujemy do odczytania wieku kota (linia 26 i 27).
Dowodem na to, że referencja zadeklarowana w main () odnosi się do obiektu stworzonego na stercie jest odczytanie adresu tej referencji. Jest on taki sam jak adres wypisany w funkcji Funkcja ().
Dobrze. Ale jak teraz zwolnić zarezerwowaną pamięć? Nie można skasować referencji za pomocą delete. Jedyne nasuwające się rozwiązanie polega na zadeklarowaniu kolejnego wskaźnika i zainicjowaniu go adresem odczytanymi z rKot. W ten sposób możemy zwolnić zarezerwowaną pamięć. Jednak i tu pojawia się kolejny