Я сподіваюся, ви зрозуміли, що все це є глибоко визначеним впровадженням, як для Java, так і для C ++. При цьому, об'єктна модель Java вимагає небагато місця.
Об'єкти C ++ (як правило) не потребують будь-якого сховища, крім того, що потрібно членам. Зауважте, що (на відміну від Java, де все визначене користувачем є еталонним типом), клієнтський код може використовувати об'єкти як тип значень, так і як типи посилань, тобто об’єкт може зберігати вказівник / посилання на інший об'єкт або безпосередньо зберігати об'єкт без непрямості Один додатковий покажчик на об'єкт необхідний, якщо є якісь virtual
методи, але досить багато корисних класів розроблені для того, щоб обійтися без поліморфізму і цього не потрібно. Немає метаданих GC та блокування кожного об'єкта. Таким чином, class IntWrapper { int x; public: IntWrapper(int); ... };
об'єкти не потребують більше місця, ніж звичайні int
s, і можуть бути розміщені безпосередньо (тобто без опосередкування) у колекціях та інших об'єктах.
Масиви складні просто тому, що в C ++ немає попередньо зробленого загального еквівалента Java-масиву. Ви можете просто виділити купу об'єктів з new[]
(без абсолютно накладних / метаданих), але немає поля довжини - реалізація, ймовірно, зберігає один, але ви не можете отримати доступ до нього. std::vector
є динамічним масивом і, таким чином, має додаткові накладні витрати та більший інтерфейс. std::array
і масиви у стилі С (int arr[N];
), потрібна константа часу компіляції. Теоретично це повинно бути просто сховище об'єкта плюс одне ціле число на довжину, але оскільки ви можете отримати динамічний розмір і повнофункціональний інтерфейс з дуже маленьким додатковим простором, ви просто до цього в практиці. Зауважте, що всі ці, як і всі інші колекції, за замовчуванням зберігають об'єкти за значенням, тим самим заощаджуючи вам непряму та простір для посилань та покращуючи кеш-поведінку. Ви повинні явно зберігати покажчики (розумні, будь ласка), щоб отримати непрямий характер.
Наведені вище порівняння не є абсолютно справедливими, оскільки деякі з цих заощаджень забезпечуються, не включаючи функції, що включають Java, а їх C ++ еквівалент часто менш оптимізований, ніж еквівалент Java (*). Загальний спосіб реалізації virtual
в C ++ накладає рівно стільки ж накладних витрат, скільки загальний спосіб впровадження virtual
в Java. Для отримання блокування вам потрібен повнофункціональний об'єкт mutex, який, швидше за все, більший, ніж кілька біт. Щоб отримати підрахунок посилань ( ніеквівалент GC, і не повинен використовуватися як такий, але іноді корисний), вам потрібен розумний вказівник, який додає поле відліку посилань. Якщо об'єкт не сконструйований обережно, кількість посилань, об'єкт розумного вказівника та посилальний об'єкт знаходяться в абсолютно окремих місцях, і навіть коли ви правильно його сконструювали, спільний покажчик може (повинен бути) ще двома вказівниками замість одного. Знову ж таки, хороший стиль C ++ не використовує цих функцій для того, щоб мати значення - на практиці добре написані об’єкти бібліотеки C ++ використовують менше. Це не обов'язково означає менше споживання пам'яті в цілому, але це означає, що C ++ має гарний початок у цьому плані.
(*) Наприклад, ви можете отримувати віртуальні дзвінки, ідентифікаційні хеш-коди та блокування лише одним словом для деяких об'єктів (і двома словами для багатьох інших об'єктів), об'єднуючи інформацію про тип із різними прапорами та видаляючи біти блокування для об'єктів, які є навряд чи будуть потрібні замки. Докладні пояснення цього та інших оптимізацій див. У впровадженні об'єктної моделі Java (PDF) Девіда Ф. Бекона, Стівена Дж. Фінка та Девіда Гроува.
int
? Якщо так, то вам слід порівняти це зint
Java, а неInteger
- поки ваші входи C ++ становлять 32 біт.