Здравствуйте, xexe2, Вы писали: X>Уважаемый ол, чему же именно равен размер объекта в куче? Собственно сначала отвечу про sizeof На самом деле для любого типа в C++ можно вычислить, кроме sizeof ещё один параметр -- выравнивание. Выравнивание -- это число, которому должны быть кратны смещения полей этого типа и которому должен быть кратен его sizeof. Посчитать выравнивание можно, например, так:
Используя эту конструкцию и sizeof можно поисследовать размеры разных объектов. А используя макрос OFFSET_OF ещё и смещениея разных явно заданных полей. 1) Для стандартных типов можно составить табличку. 2) Для случая структуры или класса без виртуальных методов и без предков размер и смещения полей вычисляются так:
тут функция округлить_вверх( a, b ) возвращает наименьшее целое n, такое что a <= n и n кратно b 3) Для случая union в качестве выравнивания берётся максимальное выравнивание поля, а в качестве sizeof максимальный sizeof поля округлённый вверх на выравниване union При этом не важно, сколь сложно устроены поля. Я пока не встретил ещё компилятора, который бы не придерживался такой стратегии. Тут в целом есть довольно мало места для произвола. Основное -- порядок итерации полей в приведённом выше алгоритме. Обычно они итерируются в порядке описания, но возможны варинаты. Немного спасает то, что для структур приходится всем компиляторам согласовывать свои правила, чтобы все могли звать API. Но в случае private секций руки у них уже довольно развязаны. 4) В классе, где есть виртуальные методы, обычно заводится дополнительные скрытыие поля, со своими sizeof и align. В принципе их можно воспринимать как поля стандартных типов. Соответсвенно поэкспериментировав с классами вида
Можно узанать значения sizeof и align этих переменных. Обычно они такие же, как и у указателя. 5) В случае простого нследования, объекты базовых типов размещаются в объекте наследнике по тому же алгоритму, что и поля. За исключением одной тонкости. Компилятор имеет право на оптимизацию, суть которой состоит в том, что можно вовсе не размещать объекты баз, в которых нет полей. Но есть тонкости, в случае, когда есть виртуальные базы. Их всего две 5.1) Наличие виртуальной базы может порождать доп. скрытые поля (может и не порождать) 5.2) объект виртуальной базы всегда один, но вот выравнивание "остатков" от его наследников может быть разным. В целом обычно компиляторы ведут себя так, что "остаток" является как бы отдельным полем, а виртуальная база отодельным. Собственно это примерно исчерпывает правила, которых обычно придержиываются компиляторе в вопросе определния sizeof объектов. При этом стоит обратить вниание на то, что обычно есть параметр компиляции, который как бы задаёт максимальное выравнивание стандартного типа. Так что если вы какую-то структуру скомпилируете со значением этого параметра, скажем 2, то потом выравнивание этой структуры будет 2, что бы вы с ней не делали. |