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