Mam nadzieję, że zdajesz sobie sprawę, że wszystko to jest ściśle zdefiniowane w implementacji, zarówno dla Java, jak i C ++. To powiedziawszy, model obiektowy Java wymaga sporo miejsca.
Obiekty C ++ (generalnie) nie potrzebują żadnej pamięci poza tym, czego potrzebują członkowie. Zauważ, że (w przeciwieństwie do Javy, gdzie wszystko, co zdefiniowane przez użytkownika jest typem referencyjnym), kod klienta może wykorzystywać obiekty zarówno jako typ wartości, jak i typy referencyjne, tzn. Obiekt może przechowywać wskaźnik / referencję do innego obiektu lub przechowywać obiekt bezpośrednio bez pośrednictwa. Jeden dodatkowy wskaźnik na obiekt jest konieczny, jeśli istnieją jakieś virtual
metody, ale całkiem sporo użytecznych klas zaprojektowano tak, aby radziły sobie bez polimorfizmu i nie potrzebują tego. Brak metadanych GC i blokady dla poszczególnych obiektów. Zatem class IntWrapper { int x; public: IntWrapper(int); ... };
obiekty nie potrzebują więcej miejsca niż zwykłe int
s i mogą być umieszczane bezpośrednio (tj. Bez pośrednictwa) w kolekcjach i innych obiektach.
Tablice są trudne, ponieważ nie ma gotowego, wspólnego odpowiednika tablicy Java w C ++. Możesz po prostu przydzielić wiązkę obiektów new[]
(bez absolutnie żadnych narzutów / metadanych), ale nie ma pola długości - implementacja prawdopodobnie przechowuje jeden, ale nie masz do niego dostępu. std::vector
jest tablicą dynamiczną, a zatem ma dodatkowe obciążenie i większy interfejs. std::array
i tablice w stylu C (int arr[N];
), potrzebujesz stałej czasowej kompilacji. Teoretycznie powinna to być tylko pamięć obiektu plus jedna liczba całkowita na długość - ale ponieważ możesz uzyskać dynamiczne zmiany rozmiaru i w pełni funkcjonalny interfejs z bardzo małą dodatkową przestrzenią, po prostu idziesz do tego w praktyce. Zauważ, że wszystkie te, a także wszystkie inne kolekcje, domyślnie przechowują obiekty według wartości, oszczędzając w ten sposób pośredniość i miejsce na referencje oraz poprawiając zachowanie pamięci podręcznej. Musisz jawnie przechowywać wskaźniki (inteligentne, proszę), aby uzyskać pośrednie.
Powyższe porównania nie są do końca uczciwe, ponieważ niektóre z tych oszczędności wynikają z nieuwzględnienia funkcji zawartych w Javie, a ich odpowiednik C ++ jest często mniej zoptymalizowany niż odpowiednik Java (*). Powszechny sposób implementacji virtual
w C ++ nakłada dokładnie tyle samo kosztów ogólnych, co powszechny sposób implementacji virtual
w Javie. Aby uzyskać blokadę, potrzebujesz w pełni funkcjonalnego obiektu mutex, który najprawdopodobniej jest większy niż kilka bitów. Aby uzyskać liczenie referencji ( nieodpowiednik GC i nie powinien być używany jako taki, ale czasem przydatny), potrzebujesz inteligentnego wskaźnika, który dodaje pole zliczania referencji. O ile obiekt nie jest skonstruowany ostrożnie, licznik referencji, obiekt inteligentnego wskaźnika i obiekt odniesienia znajdują się w całkowicie oddzielnych lokalizacjach, a nawet jeśli zbudujesz go poprawnie, wspólny wskaźnik może (musi?) Nadal mieć dwa wskaźniki zamiast jednego. Z drugiej strony, dobry styl C ++ nie wykorzystuje tych funkcji na tyle, aby miało to znaczenie - w praktyce dobrze napisane obiekty biblioteki C ++ zużywają mniej. To niekoniecznie oznacza mniejsze zużycie pamięci, ale oznacza, że C ++ ma dobry start w tym zakresie.
(*) Na przykład można uzyskać wirtualne połączenia, kody skrótu tożsamości i blokowanie za pomocą tylko jednego słowa dla niektórych obiektów (i dwóch słów dla wielu innych obiektów) poprzez połączenie informacji o typie z różnymi flagami i usunięcie bitów blokady dla obiektów, które są prawdopodobnie nie będzie potrzebował zamków. Zobacz efektywne pod względem miejsca i czasu wdrożenie Java Object Model (PDF) autorstwa Davida F. Bacona, Stephena J. Finka i Davida Grove'a, aby uzyskać szczegółowe wyjaśnienie tej i innych optymalizacji.
int
? Jeśli tak, to powinieneś porównać to zint
Javą,Integer
o ile nie masz 32-bitowych int.