Wpis z mikrobloga

Jak to jest w c++ z tworzeniem obiektów?
Widzę, że są dwa sposoby:

Object *myObject = new Object;

Object myObject;

Rozumiem, że ten pierwszy to jest sposób na dynamiczne alokowanie pamięci, to znaczy wskaźnik umieszczany jest na stosie, a na stercie ląduje obiekt. Czyli coś co jest domyślne w Javie czy C# z tą różnicą, że w C# to nie wskaźnik tylko referencja, ale jest to chyba praktycznie to samo.

Z kolei ten drugi sposób to rozumiem, że jest to alokowanie na stosie? Jeśli tak to jestem trochę zmieszany kiedy czego używać. Wiadomym jest, że szybciej działa się na elementach ze stosu, ale przecież obiekty potrafią być duże więc istnieje ryzyko przepełnienia stosu więc wydaje się to ryzykowne rozwiązanie i w takim wypadku nie rozumiem na jakiej podstawie miałbym stwierdzać czy lokować obiekt na stosie czy na stercie.

#programowanie #cpp
  • 26
@maestrozo: Pierwszy na hipie, drugi na staku, chyba że stworzysz go gobalnie poza majnem, wtedy wyląduje w sekcji zmiennych statycznych (.data). Na stosie też niekoniecznie wyląduje wskaźnik w sensie fizycznego adresu... (w sumie to zależy od optymalizacji kompilacji itp.). Normalnie #!$%@? obiekty #!$%@? na stos, bo weź pod uwagę, że obiekty tworzone na podstawie klasy string i tak gdzieś wewnętrznie używają new, który rezerwuje pamięć na hipie, więc to nie jest
@maestrozo: Ogólnie zawsze preferujesz alokacje na stosie chyba że rozmiar będzie zbyt duży albo nie znasz rozmiaru w czasie alokacji, np jak piszesz jakiś kontener.
I ogólnie new się nie używa od jakiś 10 lat, żeby alokować na stercie używa się smart pointerów jak std::unique_ptr czy std::shared_ptr.
@maestrozo: W standardzie C++ nie ma nic o stosie i stercie, jest tylko o zasięgu (życia) zmiennych. I tak:
new Object; tworzy nową zmienną o zasięgu dynamicznym, gdzie po alokacji odpowiedniej ilości pamięci wywołuje domyślny konstruktor.
Object *myObject jest automatyczną zmienną wskaźnikową przechowującą adres pamięci zaalokowany w poprzednim punkcie.
Object myObject; jest automatyczną zmienną, która zawiera obiekt w stanie po wywołaniu domyślnego konstruktora.
Zmienne automatyczne są automatycznie (sic) niszczone (destruktor
@maestrozo: Sterta w rozumieniu C# oraz innych języków które działają de facto na maszynie wirtualnej (CLR) to zupełnie inna para kaloszy. Działa tam garbage collector, którzy najczęściej jest generacyjny i on dzieli obiekty według lifetimu, dzieli sterte na różne obszary i je kompaktuje, tak że różni się to sporo od memory layout w takim C++ gdzie podział na stos/sterte jest bardziej na poziomie OSa.
Pewnie niewiele zrozumiałeś ale to nie szkodzi
@konsument: Dokładnie. Standard C++ w zasadzie nie porusza zagadnień związanych z modelem pamięci wirtualnej procesu. Tym zajmuje się kompilator, który ma wygenerować taki plik wykonywalny, który będzie spełniał założenia standardu, a implementacja działania kompilatora, to już inna bajka.
Rzeczy na stosie są niszczone, kiedy kończy się scope, więc jak chcesz np. wewnątrz funkcji utworzyć coś co będzie żyło dalej kiedy wrócisz z funkcji, to alokujesz "na stercie".


@grzegorzx86: Niby tak ale nie do końca xD W nowoczesnym C++ jednak mocno polega się na value semantics i RVO więc tworzenie zmiennych na stosie jest często jak najbardziej w porządku.