C ++ класс пустой класс размером 1 байт - PullRequest
9 голосов
/ 06 февраля 2012

Я новичок в C ++ и обнаружил странную особенность в C ++.Я увидел, что размер пустого элемента равен 1 байту, я провел некоторое исследование и выяснил, что это делается, потому что каждый объект должен иметь отдельный адрес.Но я хочу знать, каково содержание этого 1 байта, который помещен.Я знаю, что он не содержит указатель "this", но это фиктивный байт или есть какой-то контент ???

Ответы [ 8 ]

11 голосов
/ 06 февраля 2012

Нет контента. Это просто фиктивный байт.

Каждый class или struct должен иметь sizeof больше, чем 0, из-за чего ваше поведение. Это ожидается и предписано стандартом.

8 голосов
/ 06 февраля 2012

Стандарт обязывает разные объекты одного типа иметь разные адреса. Это, в свою очередь, гарантирует, что для любого объекта T, T* действует как однозначный идентификатор этого объекта (для этого типа).

Конечно, вам не нужно часто знать, действительно ли два объекта одинаковы или нет, но иногда (с учетом низкоуровневого доступа C ++) это либо необходимо, либо просто удобно.

Таким образом, указано, что ни один объект не должен иметь нулевой размер.

Однако из этого правила есть исключение: при использовании пустого класса в качестве базового класса компилятор может выбрать применение Empty Base Optimization ( EBO ) в некоторых случаях. Например:

struct Empty {};

struct Slim: Empty {
  int a;
};

static_assert(sizeof(Slim) == sizeof(int), "");

Как правило, размер базового класса добавляется, но в данном конкретном случае это не является необходимым. Однако правило о том, что два разных объекта одного типа никогда не должны иметь один и тот же адрес, по-прежнему применяется, и поэтому:

struct Fat: Empty {
  Empty e;
};

static_assert(sizeof(Fat) > sizeof(Empty), "");

EBO является основной причиной использования наследования private в шаблонных ситуациях. Например:

template <typename Allocator>
class MyClass: private Allocator {
};

Таким образом, если окажется, что Allocator - пустой класс, никаких накладных расходов не будет. В общем, поэтому он часто используется для политик , например, предикатов, которые вы передаете map.

3 голосов
/ 06 февраля 2012

Байт не содержит ничего, он делает некоторые другие варианты поведения более приятными. Например, рассмотрим случай, когда пустые классы содержатся в другом.

class Empty
{ };

class TwoEmpties
{
  Empty a;
  Empty b;
};

Возможно, вы захотите, чтобы адреса двух участников, &TwoEmpties::a и &TwoEmpties::b, были разными. Чтобы это произошло, они должны иметь размер> 1. (или компилятор должен будет добавить между ними отступы, что, в свою очередь, усложнит правила того, когда и где компилятор может добавлять отступы к классам.)

2 голосов
/ 06 февраля 2012

Вы можете использовать ваш отладчик или что-то простое, например, printf("%x", *(unsigned char *)&myobj);, чтобы просмотреть содержимое байта.Я не читал спецификацию C ++, но я бы предположил , что содержимое байта не определено, поэтому поведение зависит от компилятора и вашей ОС.

1 голос
/ 18 мая 2014

An empty class has a sizeof 1, поскольку при создании объектов этого класса они будут храниться в том же месте в памяти, если размер = 0.

Предположим, что при создании объекта address is 1000.

Если размер class is 0, следовательно, размер object must be 0.

* * 1010

Так что теперь, если сделан другой объект,

Add. of 2nd object=1000+0th location

Оба объекта имеют один и тот же адрес, и это неопределенное поведение, и оно не должно происходить, поскольку будет неопределенность в отношении того, на какой объект ссылаются.

Следовательно empty classes are given a byte of memory для предотвращения подобных ситуаций.

0 голосов
/ 07 июля 2016

Я столкнулся с подобной проблемой, и кажется, что можно определить класс с нулевой длиной с небольшим фокусом. Я не знаю, только ли это из-за g ++, но вижу следующий фрагмент кода:

struct ONE {};
struct ZERO { char x[0]; };

int main() {
  cout << sizeof(ONE) << ", " << sizeof(ZERO) << endl;

  ONE* po1 = new ONE;
  ONE* po2 = new ONE;
  cout << po1 << ", " << po2 << endl;

  ZERO* pz1 = new ZERO;
  ZERO* pz2 = new ZERO;
  cout << pz1 << ", " << pz2 << endl;
}

Вывод:

1, 0
0xe4f010, 0xe4f030
0xe4f050, 0xe4f070

Таким образом, размер пустого класса равен единице (согласно стандарту C ++), но если он имеет только поле массива нулевой длины, размер становится равным нулю. Если новый класс с действительно нулевым размером размещен в куче с new, возвращается действительный адрес, и если он назначен несколько раз, их указатели указывают на разные адреса памяти.

0 голосов
/ 19 мая 2014

Все вышеприведенные ответы неверны, насколько мне известно.Правильный ответ: по умолчанию при создании объекта класса вызывается 4 встроенные функции:

  1. Конструктор по умолчанию

  2. Деструктор по умолчанию

  3. Конструктор копирования

  4. перегруженный оператор присваиваний

, следовательно, размер пустого класса составляет 1 байт, Пример: tryэто

#include<iostream>
using namespace std;
class Test
{
};
int main()
{
Test t;
cout<< "size of empty class is "<<sizeof(t);
}
0 голосов
/ 06 февраля 2012

Это фиктивный байт - конструктор и деструктор будут тривиальными, «данные не сохраняются».

...