2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




 
 С++ странный размер класса
Сообщение04.12.2012, 17:00 
Всегда считал, что размер экземпляра класса складывается из размеров полей этого класса, но при проверке результат оказался далеким от ожиданий: вызов sizeof для экземпляров различных классов показывал размер превышающий сумму размеров полей (порой в несколько раз). Вот простой пример:
Код:
class strangeSize{
public:
   int a, b;
   strangeSize() {};
   virtual ~strangeSize() {};
};
int main()
{
    cout << sizeof(strangeSize) << endl;
    return 0;
}

Данный код выводит 12.
Как рассчитывается реальный размер экземпляра и можно ли уменьшить его до размера суммы полей?

 
 
 
 Re: С++ странный размер класса
Сообщение04.12.2012, 17:22 
Во первых, объекты некоторых классов содержат поля, неявно добавленные компилятором. Наиболее распространённое такое поле - указатель на таблицу виртуальных методов. Как можно догадаться по названию, этот указатель есть у классов с виртуальными методами, как в вашем примере. Размер этого поля обычно равен размеру указателя, 4 байта в вашем примере. Есть ещё варианты, например указатель на виртуальную базу.
Во вторых, некоторые поля могут сдвигаться для выполнения требований по выравниванию для данного процессора. Например, класс с полями char, int, char, int будет иметь размер как у 4-х int.

 
 
 
 Re: С++ странный размер класса
Сообщение04.12.2012, 17:43 
Спасибо, venco.
О том, что указатель на таблицу хранится в экземпляре не знал.
P.S. Для регулирования выравнивания существует такая конструкция:
Код:
#pragma pack(push, 1)
class myClass
{
    // ...
};
#pragma pack(pop)

 
 
 
 Re: С++ странный размер класса
Сообщение04.12.2012, 17:50 
Mr Alexey в сообщении #654136 писал(а):
P.S. Для регулирования выравнивания существует такая конструкция:
Только использовать её надо осторожно, выравнивание не зря существует.

 
 
 
 Re: С++ странный размер класса
Сообщение04.12.2012, 18:15 
Аватара пользователя
Mr Alexey в сообщении #654136 писал(а):
P.S. Для регулирования выравнивания существует такая конструкция

не переносимая. Избегайте непереносимого кода.

 
 
 
 Re: С++ странный размер класса
Сообщение05.12.2012, 01:54 
Mr Alexey в сообщении #654136 писал(а):
О том, что указатель на таблицу хранится в экземпляре не знал.

А где ему храниться, интересно? Таблица виртуальных функций — это, в сущности, runtime-тип объекта, который просто необходимо знать для реализации полиморфизма.

Ну а так есть еще одна возможность: у объектов в debug сборках от майкрософтовского компилятора бывают отладочные поля (и поэтому debug и release сборки бинарно несовместимы... фанаты *nix хохочут и показывают языки, я так полагаю).

И да, не надо ручками лезть в выравнивание. Вы выиграете пять килобайт места, а проиграете тридцать процентов процессорных тактов — а если, не дай бог, ваш код попытаются запустить на ARM'е, он просто вылетит с misaligned access.

 
 
 
 Re: С++ странный размер класса
Сообщение05.12.2012, 06:59 
Аватара пользователя

(В защиту ручного управления выравниванием)

У структур, входящих в интерфейсы модулей (не классов, конечно) бывает полезно фиксировать выравнивание, чтобы избежать проблем с "разъезжанием" структур внутри программы и во внешнем модуле (собираемом другим компилятором)

 
 
 
 Re: С++ странный размер класса
Сообщение05.12.2012, 15:25 
Аватара пользователя

(Оффтоп)

Joker_vD в сообщении #654387 писал(а):
а если, не дай бог, ваш код попытаются запустить на ARM'е, он просто вылетит с misaligned access.

Скорей, просто при компиляции на ARM выравнивание будет сделано по требованиям архитектуры, что бы там ни запросил программист. Проблема может возникнуть только при передаче данных между системами, скажем, в канале связи x86-ARM. Но форматирование данных для каналов связи - отдельная история, и если правильно его сделать, всё будет окей.

worm2 в сообщении #654408 писал(а):
внутри программы и во внешнем модуле (собираемом другим компилятором)

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

 
 
 
 Re: С++ странный размер класса
Сообщение05.12.2012, 18:09 

(Оффтоп)

Munin в сообщении #654525 писал(а):
Но форматирование данных для каналов связи - отдельная история

Ага, это очень заманчиво: просто сказать send(socket, (char*)&myStruct, sizeof myStruct, flags). Но увы, выравнивание, порядок байт в слове и т.п. разбивают такие мечты вдребезги. Поэтому лучше явно где-то выписать формат данных в канале, и уже приводить к нему/от него.

 
 
 
 Re: С++ странный размер класса
Сообщение05.12.2012, 23:03 
Аватара пользователя

(Оффтоп)

Ага, заманчиво, до первой набитой шишки. Потом наступает просветление и стадия google serialization.

 
 
 [ Сообщений: 10 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group