Do alokowania pamięci (albo raczej: tworzenia obiektów na stercie) służy w C++ operator o wiele mówiącej nazwie new
. Chociaż jest on powszechnie znany i nieustannie używany przez każdego programistę C++, pewni nie wszyscy wiedzą, że występuje on nie w jednej, ale aż w czterech odmianach, z których każda różni się sposobem wywołania!
Oto krótki przegląd:
new
(co obejmuje też formę tablicową new[]
) jest oczywiście najbardziej znany i najczęściej stosowany. Warto pamiętać, że zazwyczaj robi on dwie rzeczy: oprócz alokacji pamięci wywołuje też konstruktor dla tworzonego obiektu (lub obiektów w tablicy), któremu możemy też podać parametry.new
zmienia natomiast swoje zachowanie tylko w zakresie tej pierwszej czynności, czyli samej alokacji. Ciekawostką jest to, że możemy wyposażyć go (tj. sam operator new
) w dodatkowe parametry – czyli przeciążyć go w pełnym znaczeniu tego słowa! Typowym przykładem, jaki się tutaj zwykle przytacza, jest następująca funkcja:
Naturalnie możliwe są bardziej przydatne zastosowania. Jeśli mamy na przykład kilka rozłącznych ze sobą stert, to możemy tak napisać operator new
, by poprzez dodatkowy argument pozwalał decydować o tym, którą z nich chcemy w danym przypadku wybrać.
new
nierzucający wyjątków. Domyślnie alokacja za pomocą new
rzuca wyjątek std::badalloc
, jeżeli operacja się nie powiodła (zwykle z powodu braku pamięci). To zachowanie – wymagające do poprawnej obsługi bloku try-catch
może nam się nie podobać, ale na szczęście można je zmienić. Wystarczy użyć wersji new
z dodatkowym parametrem std::nothrow
:
Wymaga to jeszcze dołączenia standardowego pliku nagłówkowego o wielce trafnej nazwie new.
new
, co nie ma żadnego specjalnie dobrego tłumaczenia na język polski. Użycie tego operatora wymaga podania wskaźnika na już zaalokowany kawałek pamięci. Działanie operatora new
ogranicza się wtedy do skonstruowania obiektu w tym właśnie miejscu, na które pokazuje przekazany wskaźnik. Tak więc w tym przypadku new
tak naprawdę niczego nie alokuje; jest to po prostu najzupełniej legalny sposób na wywołanie konstruktora bez robienia czegokolwiek innego. Jakkolwiek może to się wydawać przydatne, zdecydowanie odradzam korzystania z tego mechanizmu w sposób nieprzemyślany, bo można przy tym popełnić “ciekawe” błędy.Mamy więc aż cztery różne warianty new
, ale raczej nie powinno to rodzić dylematów w rodzaju “Który z nich wybrać?”. W praktyce i tak nieczęsto zachodzi potrzeba skorzystania z któregokolwiek poza pierwszym. Co nie znaczy rzecz jasna, że nie warto znać pozostałych – podobnie jak całej masy innych kruczków języka C++ :]
A propo ostatniego “new” i tekstu “obiekty są pamiętliwe” to ten problem dotyczy wszystkich obiektów.
Foo* o = new Foo();
o->Time = 10.0f;
delete o;
Foo* o2 = new Foo();
…
Pytanie: jaką wartość będzie mieć zmienna Time w drugim obiekcie ? (dodam że konstruktor jej nie inicjalizuje :)
A co do tego że nie działał Ci placement new, to głównie dlatego że twoja klasa CTexture dziedziczyła po IDxResource co już samo to było słabym pomysłem :)
Owszem było :)
A co do pytania… Jeśli faktycznie 10.0f, to wyłącznie przypadek i zachowanie zależne od implementacji sposobu zarządzania stertą. Naturalnie świadczy ono jak najlepiej o tym sposobie (ponowne wykorzystanie zwolnionych bloków). Nie zmienia to jednak faktu, że jeśli nie inicjujemy tego pola w konstruktorze, to powinniśmy je traktować jako zawierające wartość nieokreśloną.
placement new – Tlumacza na new ‘umieszczajcacy’
@up
Sądzę, że większość osób wie co oznacza placement ^^’. Sęk w tym by ująć to jakoś zgrabnie.