Wyliczanie wyrażenia obiekty tymczasowe Bogdan Kreczmer ZPCiR IIAiR PWr pokój 307 budynek C3 bogdan.kreczmer@pwr.wroc.pl Copyright c 2013 Bogdan Kreczmer Niniejszy dokument zawiera materiały do wykładu na temat programowania obiektowego. Jest on udostępniony pod warunkiem wykorzystania wyłacznie do własnych prywatnych potrzeb i może on być kopiowany wyłacznie w całości, razem z niniejsza strona tytułowa.
Czas życia obiektów tymczasowych int main( ) NazWektor W a( a, 1, 2), W b( b, 1, 1), W c( c, 1, 0), W d( d, 2, 2), W r( r ); cout << - Poczatek operacji dodawania << endl; W r = (W a + W b) + (W c + W d); cout << - Koniec operacji dodawania - << endl; cout << - Rezultat: << W r << endl; Wykonywaniu poszczególnych operacji towarzyszy tworzenie się obiektów tymczasowych. Chcac prześledzić ten proces, należy przeciażyć odpowiednie konstruktory. Przeciażenia te musza zapewniać możliwość nazwania obiektów, tak aby można było prześledzić okres życia poszczególnych obiektów. Copyright c 2013 Bogdan Kreczmer Wyliczanie wyrażenia obiekty tymczasowe 1
Czas życia obiektów tymczasowych class NazWektor // static char ZnakCyfry; string Nazwa; NazWektor(const char Nazwa, float x = 0, float y = 0 ); NazWektor( const NazWektor & W ); NazWektor( ); NazWektor operator + ( const NazWektor & W ) const; NazWektor & operator = ( const NazWektor & W ); ; char NazWektor:: ZnakCyfry = 0 ; ostream & operator << ( ostream & ostrm, const NazWektor & W ) return ostrm << W. Nazwa << ( << W. x <<, << W. y << ) ; int main( ) NazWektor W( a, 1, 2 ); cout << W << endl; Wynik działania: a(1, 2) Wprowadzenie dodatkowego pola statycznego pozwala numerować tworzace się tymczasowe obiekty. Zaś pole Nazwa pozwala nazywać każdy z obiektów. Copyright c 2013 Bogdan Kreczmer Wyliczanie wyrażenia obiekty tymczasowe 2
Definicje konstruktora i destruktora class NazWektor // static char ZnakCyfry; string Nazwa; NazWektor(const char Nazwa, float x = 0, float y = 0 ); NazWektor( ); ; NazWektor::NazWektor( const char Nazwa, float x, float y ): Nazwa(Nazwa) x = x; y = y; cout << ++ Konstruktor: << this << endl; NazWektor:: NazWektor( ) cout << ++ Destruktor: << this << endl; int main( ) NazWektor W( a, 1, 2 ); Wynik działania: ++ Konstruktor: a(1, 2) Destruktor: a(1, 2) Wywołanie konstruktora lub destruktora jest sygnalizowane odpowiednim komunikatem na wyjściu standardowym. Podaje on nazwę i wartości pól obiektu. Copyright c 2013 Bogdan Kreczmer Wyliczanie wyrażenia obiekty tymczasowe 3
Konstruktor kopiujacy class NazWektor // static char ZnakCyfry; string Nazwa; NazWektor( const NazWektor & W ); ;. NazWektor::NazWektor( const NazWektor & W ): Nazwa( Tmp ) Nazwa += ++ ZnakCyfry; x = y = 0; cout <<.. Kopiuje: << this << <- << W << endl; x = W. x; y = W. y; int main( ) NazWektor W( a, 1, 2 ); NazWektor V(W); Wynik działania: ++ Konstruktor: a(1, 2) ++ Kopiuje: Tmp1(0,0) <- a(1, 2) Destruktor: Tmp1(1, 2) Destruktor: a(1, 2) Konstruktor kopiujacy w tym rozwiazaniu nie powoduje przepisanie nazwy obiektu. Jest to niezbędne, aby móc zidentyfikować nowy obiekt. Jego nazwa tworzona jest automatycznie. Copyright c 2013 Bogdan Kreczmer Wyliczanie wyrażenia obiekty tymczasowe 4
Operator dodawania class NazWektor // static char ZnakCyfry; string Nazwa; NazWektor operator + ( const NazWektor& W ) const; ;. NazWektor NazWektor::operator + ( const NazWektor& W ) const cout <<.. Dodanie: << this << + << W << endl; string Nazwa( Tmp ); Nazwa += ++ ZnakCyfry; return NazWektor( Nazwa.c str(), x+w. x, y+w. y ); int main( ) NazWektor W( a, 1, 2 ); W = W + W; Wynik działania: ++ Konstruktor: a(1, 2).. Dodanie: a(1, 2) + a(1,2) ++ Konstruktor: Tmp1(2, 4) Destruktor: Tmp1(2, 4) Destruktor: a(1, 2) W trakcie realizacji operacji dodawania tworzony jest obiekt tymczasowy, który przekazuje na zewnatrz wynik działania. Copyright c 2013 Bogdan Kreczmer Wyliczanie wyrażenia obiekty tymczasowe 5
Operator przypisania class NazWektor // static char ZnakCyfry; string Nazwa; NazWektor & operator = ( const NazWektor & W ); ;. NazWektor & NazWektor::operator = ( const NazWektor & W ) cout <<.. Podstawienie: << this << = << W << endl; x = W. x; y = W. y; return this ; int main( ) NazWektor W( a, 1, 2 ); W = W; Wynik działania: ++ Konstruktor: a(1, 2).. Podstawienie: a(1, 2) = a(1,2) Destruktor: a(1, 2) Realizacja operacji podstawienia nie wymaga tworzenia żadnych obiektów tymczasowych. Zarówno argument, jak też wynik działania, zwracane sa przez referencje. Copyright c 2013 Bogdan Kreczmer Wyliczanie wyrażenia obiekty tymczasowe 6
W r = (W a + W b) + (W c + W d) class NazWektor //.. static char ZnakCyfry; string Nazwa; NazWektor(const char Nazwa, float x = 0, float y = 0); NazWektor( const NazWektor & W ); NazWektor( ); NazWektor operator + ( const NazWektor & W ) const; NazWektor & operator = ( const NazWektor & W ); ;. int main() NazWektor Wa( a,1,2), Wb( b,1,1), Wc( c,1,0), Wd( d,2,2); NazWektor Wr( r ); cout << Poczatek operacji dodawania - << endl; Wr = (Wa + Wb) + (Wc + Wd); cout << Koniec operacji dodawania - << endl; cout << Rezultat: << Wr << endl; Wynik działania: ++ Konstruktor: a(1, 2) ++ Konstruktor: b(1, 1) ++ Konstruktor: c(1, 0) ++ Konstruktor: d(2, 2) ++ Konstruktor: r(0, 0) Poczatek operacji dodawania -.. Dodanie: c(1, 0) + d(2, 2) ++ Konstruktor: Tmp1(3, 2).. Dodanie: a(1, 2) + b(1, 1) ++ Konstruktor: Tmp2(2, 3).. Dodanie: Tmp2(2, 3) + Tmp1(3, 2) ++ Konstruktor: Tmp3(5, 5).. Podstawienie: r(0, 0) = Tmp3(5, 5) ++ Destruktor: Tmp3(5, 5) ++ Destruktor: Tmp2(2, 3) ++ Destruktor: Tmp1(3, 2) Koniec operacji dodawania Rezultat: r(5, 5) ++ Destruktor: r(5, 5) ++ Destruktor: d(2, 2) ++ Destruktor: c(1, 0) ++ Destruktor: b(1, 1) ++ Destruktor: a(1, 2) Copyright c 2013 Bogdan Kreczmer Wyliczanie wyrażenia obiekty tymczasowe 7
W r = (W a + W b) + (W c + W d) Poczatek operacji dodawania -.. Dodanie: c(1, 0) + d(2, 2) ++ Konstruktor: Tmp1(3, 2).. Dodanie: a(1, 2) + b(1, 1) ++ Konstruktor: Tmp2(2, 3).. Dodanie: Tmp2(2, 3) + Tmp1(3, 2) ++ Konstruktor: Tmp3(5, 5).. Podstawienie: r(0, 0) = Tmp3(5, 5) ++ Destruktor: Tmp3(5, 5) ++ Destruktor: Tmp2(2, 3) ++ Destruktor: Tmp1(3, 2) Koniec operacji dodawania Rezultat: r(5, 5) W r = (W a + W b) + (W c + W d); W r = (W a + W b) + Tmp1 ; W r = (W a + W b) + Tmp1 ; W r = Tmp2 + Tmp1 ; W r = Tmp2 + Tmp1 ; W r = Tmp3 ; W r = Tmp3 ; W r ; W trakcie realizacji całej operacji tworza się obiekty pośrednie, które przekazuja wyniki częściowe. Wszystkie one kończa swoje istnienie wraz z zakończeniem realizacji danej operacji, tzn. wtedy gdy sterowanie przekroczy znak średnika. Copyright c 2013 Bogdan Kreczmer Wyliczanie wyrażenia obiekty tymczasowe 8
Zapobieganie tworzeniu obiektów tymczasowych class Wektor3f //.. NazWektor3f operator + ( Wektor3f W ) const return W += this ; Wektor3f & operator += ( const Wektor3f & W ) x += W. x; y = W. y; return this ; ;.. Wektor3f W1, W2, W3; W1 = W2 + W3; = (W1 = W2) += W3; Ilość obiektów tymczasowych: 2 Ilość obiektów tymczasowych: 0 Stosujac bardziej przemyślany zapis operacji arytmetycznych można całkowicie wyeliminować tworzenie się obiektów tymczasowych. Copyright c 2013 Bogdan Kreczmer Wyliczanie wyrażenia obiekty tymczasowe 9
Podsumowanie Przy stosowaniu przeciażeń operatorów zapis złożonych działań zazwyczaj wiaże się z powstawaniem obiektów tymczasowych. Ich liczbę można prawie zawsze ograniczyć lub całkowicie je wyeliminować. Powoduje to jednak utratę czytelności zapisu takiego działania. W przypadku gdy wymagania czasowe nie sa krytyczne właściwym może być zachowanie przejrzystości zapisu kosztem efektywności wykonywanych operacji. Takie podejście jest szczególnie pomocne w poczatkowej fazie tworzenia oprogramowania, gdyż zapobiega powstawaniu przypadkowych błędów w implementowanych wzorach. Copyright c 2013 Bogdan Kreczmer Wyliczanie wyrażenia obiekty tymczasowe 10
Pytania i ćwiczenia 1. Jeżeli byłaby możliwa następujaca definicja konstruktora kopiujacego kopiujacego: class Klasa public: Klasa( Klasa Ob ) ; to jakie byłyby konsekwencje w momencie jego użycia. 2. Zakładajac, że klasa Wektor3f jest tak samo zdefiniowana jak w prezentowanym wcześniej przykładzie, należy wyznaczyć liczbę powstajacych obiektów tymczasowych dla wyrażenia: Wr = Wa + Wb + Wc + Wd; Copyright c 2013 Bogdan Kreczmer Wyliczanie wyrażenia obiekty tymczasowe 11