Каков размер пустого класса в C ++, Java? - PullRequest
14 голосов
/ 25 января 2011

Каков размер пустого класса в C ++ и Java? Почему это не ноль? sizeof(); возвращает 1 в случае C ++.

Ответы [ 8 ]

26 голосов
/ 25 января 2011

Краткий ответ:

Стандарт прямо говорит, что класс не может иметь нулевой размер.

Длинный ответ:

Поскольку каждый объект должен иметь уникальный адрес (также определенный в стандарте), у вас не может быть объектов нулевого размера.
Представьте себе массив объектов нулевого размера. Поскольку они имеют нулевой размер, они все выстраиваются в одну и ту же адресную папку. Поэтому проще сказать, что объекты не могут иметь нулевой размер.

Замечания:

Даже если объект имеет ненулевой размер, если он фактически занимает нулевую комнату, ему не нужно увеличивать размер производного класса:

Пример:

#include <iostream>

class A {};
class B {};
class C: public A, B {};

int main()
{
     std::cout << sizeof(A) << "\n";
     std::cout << sizeof(B) << "\n";
     std::cout << sizeof(C) << "\n";  // Result is not 3 as intuitively expected.
}

g++ ty.cpp
./a.out
1
1
1
15 голосов
/ 25 января 2011

В случае Java:

  • Не существует простого способа узнать, сколько памяти занимает объект в Java; т.е. нет оператора sizeof.
  • Есть несколько способов (например, использование Instrumentation или сторонних библиотек), которые дадут вам число, но значение имеет нюанс 1 ; см. В Java, как лучше всего определить размер объекта?
  • Размер объекта (пустой или непустой) зависит от платформы.

Размер экземпляра «пустого класса» (т. Е. java.lang.Object) не равен нулю, поскольку у экземпляра есть неявное состояние, связанное с ним. Например, требуется состояние:

  • , чтобы объект мог функционировать как примитивная блокировка,
  • для представления своего хеш-кода,
  • чтобы указать, был ли объект завершен,
  • для ссылки на класс времени выполнения объекта,
  • для хранения битов метки GC объекта,
  • и т. Д.

Текущие JVM Hotspot используют хитрые трюки для представления состояния в заголовке объекта, который занимает два 32-битных слова. (Это расширяется при некоторых обстоятельствах; например, когда фактически используется примитивная блокировка или после вызова identityHashCode().)


1 - Например, включает ли размер строкового объекта, созданного new String("hello"), размер этого вспомогательного массива, который содержит символы? С точки зрения JVM этот массив является отдельным объектом!

4 голосов
/ 25 января 2011

Поскольку объект должен иметь адрес в памяти и адрес в памяти, он должен занимать «некоторую» память.Так, обычно в C ++ это наименьшее возможное количество, то есть 1 символ (но это может зависеть от компилятора).В Java я не был бы так уверен ... у него могли бы быть некоторые данные по умолчанию (больше, чем просто заполнитель как в C ++), но было бы удивительно, если бы это было намного больше, чем в C ++.

4 голосов
/ 25 января 2011

Поскольку каждый объект C ++ должен иметь отдельный адрес, невозможно иметь класс с нулевым размером (кроме некоторых особых случаев, связанных с базовыми классами).В C ++ есть дополнительная информация: каков размер объекта пустого класса? .

3 голосов
/ 25 января 2011

C ++ требует, чтобы его обычное создание имело размер как минимум 1 (может быть больше, хотя я не знаю компилятора, который это делает).Однако он допускает «пустую оптимизацию базового класса», поэтому, хотя класс имеет минимальный размер 1, когда он используется в качестве базового класса, он не должен добавлять что-либо к размерупроизводный класс.

Я бы думаю Java, вероятно, делает то же самое.Причина, по которой C ++ требует размер как минимум 1, заключается в том, что каждый объект должен быть уникальным.Рассмотрим, например, массив объектов с нулевым размером.Все объекты будут находиться по одному адресу, поэтому у вас будет только один объект.Принятие нуля звучит как рецепт проблем ...

2 голосов
/ 25 января 2011

Это определяется стандартом C ++ как «ненулевое значение», потому что выделенный объект должен иметь ненулевой размер, чтобы иметь отдельный адрес. Однако класс, который наследуется от пустого класса, не должен увеличиваться в размере, за исключением обычного увеличения виртуальной таблицы, если задействованы виртуальные функции.

0 голосов
/ 25 января 2011

Как уже отмечали другие, объекты C ++ не могут иметь нулевой размер.Классы могут иметь нулевой размер только тогда, когда они действуют как подкласс другого класса.Взгляните на ответ @Martin York для описания с примерами, а также посмотрите и проголосуйте за другие ответы, которые являются правильными в этом отношении.

На Java, в горячая точка VM , в каждом объекте есть служебная память из 2 машинных слов (обычно 4 байта в 32 арках на слово) для хранения информации бухгалтерского учета вместе с информацией о типе времени выполнения.Для массивов требуется третье слово для хранения размера.Другие реализации могут занимать другой объем памяти (классическая Java VM, по той же ссылке, занимала 3 слова на объект)

0 голосов
/ 25 января 2011

Я не знаю, есть ли в java оператор sizeof (). Что вы можете сделать, это создать экземпляр пустого класса (иметь его сериализуемость), отправить его через PipedOutputStream и прочитать его как байтовый массив - byteArray.length даст вам размер.

В качестве альтернативы, запишите экземпляр в файл, используя DataOutputStream, закройте файл, откройте его, и file.length () даст вам размер объекта. Надеюсь, это поможет, - М.С.

...