Pseudo-przypisanie następuje wtedy gdy ktoś przypisuje obiekt do niego samego. Przykład:
Oczywiście nikt nigdy nie popełnia tak jaskrawych przykładów pseudo-przypisań, ale odkąd więcej niż jeden wskaźnik lub referencja może odwoływać się do tego samego obiektu (aliasing), możesz utworzyć takie przypisanie nie wiedząc o tym:
[ Góra | Dół | Poprzednia sekcja | Następna sekcja | Szukaj w FAQ ]
Jeśli nie będziesz się przejmował pseudo-przypisaniami, narazisz swoich użytkowników na bardzo subtelne bugi, które mają bardzo subtelne i często katastrofalne symptomy. Na przykład, znajdująca się poniżej klasa spowoduje kompletną katastrofę w przypadku pseudo-przypisania:
Jeśli ktoś przypisze obiekt Fred do niego samego, linia #1 usunie this->p_ i f.p_ ponieważ *this i f są tym samym obiektem. Ale w linii #2 używamy *f.p_, który nie jest już poprawnym obiektem. To spowoduje poważną katastrofę.
Ty jako autor klasy Fred jesteś odpowiedzalny za to, by wykluczyć możliwość pseudo-przypisania obiektu Fred. Nie zakładaj, zę inni użytkownici nigdy nmie zrobią czegoś takiego z twoimi obiektemami. To jest tylko twoja wina jeśli obiekt nie poradzi sobie z pseudo-przypisaniem.
Na marginesie: Powyższe wyrażenie Fred::operator= (const Fred&) zawiera także drugi problem: Jeśli zostanie zgłoszony [ang. throw] wyjątek w czasie szacowania new Wilma(*f.p_) (np. wyjątek out-of-memory lub wyjątek w konstruktorze kopii Wilmy), this->p_ będzie wskaźnikiem zawiszonym [ang. dangling pointer] będzie wskazywał na mijesce pamięci, które nie jest już prawidłowy. Można temu zapobiec poprzez alokowanie nowych obiektów przed kasowaniem starych.
[ Góra | Dół | Poprzednia sekcja | Następna sekcja | Szukaj w FAQ ]
Powinieneś martwić się pseudo-przypisaniem za każdym razem kiedy tworzysz klasę. Nie oznacza to że musisz dodawać ekstra kod do wszystkich swoich klas: dopóki twoje obiekty płynnie radzą sobie z pseudo-przypisaniem dopóty nie ma znaczenia wstawianie dodatkowego kodu.
Jeśli musisz wstawić dodatkowy kod do swojego przypisania, oto prosty i efektywny sposób:
Taki jawny test nie jest zawsze konieczy. Na przykład, gdybyśmy mieli poprawić operator przypisania w poprzednim faq tak, by radził sobie z wyjątkami zgłaszanymi przez new i/lub z wyjątkami zgłaszanymi przez konstruktor kopii klasy Wilma, moglibyśmy zastosować poniższy kod. Zauważ, że ten kod posiada (sympatyczny) efekt uboczny, jakim jest automatyczne radzenie sobie również z pseudo-przypisaniem:
W przypadkach takich jak powyższy przykład (gdzie pseudoprzypisanie jest nieszkodliwe ale wpływające na efektywność), część programistów chce poprawić ową efektywność poprzez dodanie całkiem niepotrzebnego testu, jak "if (this == &f) return *this;". Generalnie jest to przejaw złego myślenia. Dla przykładu, dodywanie powyżeszgo if do opertora Fred uczyni wszystkie inne przypadki przypisań mniej efektywnymi (dodatkowy (i niepotrzebny) test warunkowy). Jeśli pseudo-przypisanie pojawi się raz na tysiąc razy, if zmarnuje 99.9% cyklów czasowych.
[ Góra | Dół | Poprzednia sekcja | Następna sekcja | Szukaj w FAQ ]
E-mail the author
[ C++ FAQ Lite
| Spis treści
| Skorowidz
| O autorze
| ©
| Pobierz swoją własną kopię ]
Ostatnia aktualizacja Jun 17, 2002
Wersja polska: 0.1i Jul 12, 2004