Blog programisty o C/C++ i PHP

Programowanie w C/C++ i PHP. Blog pełen wskazówek, porad, analiz i opisów.

Obiekty tymczasowe i zwracanie wskaźników przez metody.

kwiecień 18th, 2010 in Programowanie w C++

Kiedy tylko przychodzi nam skracać kod i usuwać zmienne lokalne na rzecz pojedynczej sekwencji wywołań upewnijmy się że nie zwracamy wskaźnika.

Załóżmy że mamy taki kod, w którym dostępna jest nasza klasa AClass oraz AClassState. AClass zawiera metodę zwracającą wskaźnik do obiektu reprezentującego jej stan AClassState*
Zbadajmy teraz temat obiektów tymczasowych w następujący sposób:


class AClassState
{
public:
	void saveToXml(ofstream& ofs)
	{
		cout << "Save AClassState to xml" << endl;
	}
};

class AClass
{
public:

	AClassState* getState()
	{
		return new AClassState();
	}

	~AClass()
	{
		cout << "Destroy AClass object" << endl;
	}
};

AClass getAClassObject()
{
	return AClass();
}
...
AClass getAClassObject()
{
	return AClass();
}

ofstream ofs("objectState.xml");
getAClassObject().getState()->saveToXml(ofs);

...

Teoretycznie jest ok, a w dodatku krótko i zwięźle, ale … no i tu zaczyna się problem z obiektem tymczasowym klasy AClass zwróconym przez funkcje getAClassObject(). Czas życia naszego obiektu jest jednak krótszy niż do końca “pełnego wyrażenia”. Nie ma więc gwarancji, że po zakończeniu wywołania metod getState() nie dostaniemy wskaźnika na obiekt za chwilę nie zostanie srzątnięty !

Są 2 przypadki błędogenne:
1. wskaźnikami obiektów stanu nie zarządza nasz obiekt, więc są tworzone i ich pamięć nigdy nie będzie zwolniona (wyciek pamięci), aczkolwiek metoda saveToXml() wykona się na prawidłowym obiekcie i nie będzie błędów
2. wskaźniki stanu są niszczone w destruktorze naszej klasy, a zatem nie będzie wycieków pamięci, ale wywołanie metody saveToXml() może nie być prawidłowe, gdyż destruktor naszej klasy wywoła się przed zakończeniem całego wyrażenia. W tej sytuacji nie mamy absolutnie żadnej gwarancji, że operujemy tym obiektem stanu którego oczekiwaliśmy.

Aha, jeszcze jedna dość istotna kwestia, dla uproszczenia założyłem w swoich rozważaniach, że obiekt stanu kompletnie nie zna (nie odwołuje się do) obiektu naszej klasy. Relacja w drugą stronę jest jak najbardziej oczywista i zasadna.

Rozwiązanie: jeśli musisz używać obiektów tymczasowych to stosuj przypadek 2 (bez wycieków pamięci) i dodatkowo napisz w klasie AClass własny konstruktor bezparametrowy (nawet gdyby miał nic nie robić). Wtedy destruktor tej klasy wykona się tak jak to napisał standard C++, czyli na koniec wyrażenia. Ale jak nie musisz to nie polegaj na tymczasowych obiektach zwracających gołe wskaźniki poza klasę.

Tags: ,

One Response to “Obiekty tymczasowe i zwracanie wskaźników przez metody.”

  • noisy.pl
    czerwiec 23rd, 2010 at 20:49

    Jak już powołujesz się na standard, to mógłbyś zarzucić jakimś konkretnym fragmentem?

    zaciekawiło mnie to…

Leave a Reply