Мой класс содержит 1 enum, 2 int и указатель.У него нет виртуальных функций, но он измеряет 20 байтов.Зачем? - PullRequest
2 голосов
/ 20 февраля 2012

согласно названию. Я действительно не хочу перечислять все другие элементы, которые он содержит, но я был удивлен, обнаружив, что с учетом того, что единственными нестатическими элементами данных были enum, 2 из int и указатель на его собственный тип, это sizeof должно быть 20.

У него нет виртуальных функций, и я измерил указатель и enum как 4 байта каждая. Должен ли я выглядеть сложнее для других участников?

Мне нужна эта информация, чтобы выделить буфер для n объектов его типа при чтении из файла.

Платформа: bada, Environment: gcc и Eclipse в Win 7 x64.

enum blockParams {enum1, enum2, /**/};
class Block : public Object {
public:
    int begin;
protected:
    Block() : begin(-1), end(UNCLOSEDBLOCK) {}
    //Last index
    int end;
private:
    blockParams1 params;
    const Block *parentBlock;
//Lots and lots (~80) member functions and static data members.
}

Ответы [ 4 ]

6 голосов
/ 20 февраля 2012

Компилятор может свободно добавлять отступы между членами для достижения различных требований выравнивания.

Многие компиляторы предлагают непереносимый способ более плотной упаковки структуры (например, GCC __attribute ((packed))), но редкохорошая причина использовать это.

5 голосов
/ 20 февраля 2012

Когда я вижу базовый тип с именем Object, я действительно сомневаюсь в утверждении об отсутствии виртуальных функций.

1 голос
/ 20 февраля 2012

Если вы правильно используете sizeof, вам не нужно знать размер структуры, компилятор будет правильно рассчитывать размер вашего буфера.

Размер 20, вероятно, включает отступы, добавленные компилятором для повышения эффективности.

0 голосов
/ 20 февраля 2012

Размер - это сумма частей + отступов.

int main()
{
    std::cout << "Object:       " << sizeof(Object) << "\n";
    std::cout << "int:          " << sizeof(int) << "\n";
    std::cout << "blockParams1: " << sizeof(blockParams1) << "\n";
    std::cout << "Block*:       " << sizeof(Block*) << "\n";

    int estimatedSize = sizeof(Object) + (2 * sizeof(int)) + sizeof(blockParams1) + sizeof(Block*);
    int actualSize    = sizeof(Block);

    std::cout << "Block:        " << actualSize << "\n";
    std::cout << "Padding + implementation defined data for virtual functions:      " <<  (actualSize - estimatedSize) << "\n";
}

Запуск этого объекта с пустым объектом:

> ./a.out
Object:       1 // Note: This may be optimized away in Block.
                //       All objects must have non 0 size but when they are a base class
                //       you can optimize an actual zero sized object away.
int:          4
blockParams:  4
Block*:       8
Block:        24
Padding + implementation defined data for virtual functions:      3
// Note because the Object size 1 will be optimized away this is actually 4.

Запуск этого объекта с виртуальным деструктором

> ./a.out
Object:       8
int:          4
blockParams:  4
Block*:       8
Block:        32
Padding + implementation defined data for virtual functions:      4
// Note It will use the area in Object for virtual functions so it does not
//      Explicitly need any itself (in this implementation using a vtable).

Если мы предполагаем, что указатели на вашей платформе имеют 4 байта (и у вас есть Object с виртуальными функциями).Я бы ожидал увидеть:

> ./a.out
Object:       4
int:          4
blockParams:  4
Block*:       4
Block:        20
Padding + implementation defined data for virtual functions:      0
...