Как объекты хранятся в памяти в C ++? - PullRequest
9 голосов
/ 01 января 2009

Как объекты хранятся в памяти в C ++?

Для обычного класса, такого как

class Object
    {
public:
    int i1;
    int i2;
    char i3;
    int i4;
private:
    };

Использование указателя объекта в качестве массива может использоваться для доступа к i1 следующим образом?

((Object*)&myObject)[0] === i1?

Другие вопросы по SO, похоже, предполагают, что приведение структуры к указателю будет указывать на первый член для POD-типов. Чем это отличается для классов с конструкторами, если вообще? Кроме того, чем он отличается для не POD-типов?

Edit:

Следовательно, в памяти будет ли приведенный выше класс выглядеть следующим образом?

[i1 - 4bytes][i2 - 4bytes][i3 - 1byte][padding - 3bytes][i4 - 4bytes]

Ответы [ 5 ]

16 голосов
/ 01 января 2009

Почти. Вы бросаете объект *, и забыли взять адрес. Давайте еще раз спросим следующее:

((int*)&myObject)[0] == i1

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

Обратите внимание, что я не буду так быстро говорить вам, что это сработало бы, если бы вы спросили о i3 - в этом случае, даже для простого POD, выравнивание или порядковый номер могут легко вас испортить.

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

Ответ на ваши изменения: Если это все определение вашего класса, и вы используете один из основных компиляторов с опциями по умолчанию и работаете на процессоре x86, то да, вы, вероятно, догадались о правильном расположении памяти. Но выбор компилятора, параметров компилятора и другой архитектуры процессора может легко опровергнуть ваши предположения.

5 голосов
/ 01 января 2009

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

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

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

3 голосов
/ 01 января 2009

Разница в том, что этот прием действителен только для типов POD. Это действительно все, что нужно сделать. Стандарт определяет, что это приведение действительно для типа POD, но не дает никаких гарантий относительно того, что происходит с типами, отличными от POD.

2 голосов
/ 03 января 2009

Это на самом деле зависит от компилятора, точнее, от компилятора зависит определение структуры памяти.

Например, сочетание открытых, закрытых и защищенных переменных-членов может быть расположено так, чтобы каждый тип доступа был непрерывным. Или у производных классов могут быть переменные-члены, чередующиеся с неиспользуемым пространством в суперклассе.

Ситуация ухудшается с виртуальным наследованием, где виртуально унаследованные базовые классы могут быть размещены в любом месте в памяти, выделенной для этого конкретного экземпляра.

POD отличается тем, что должен быть совместим с C.

0 голосов
/ 01 января 2009

Обычно важно не то, имеет ли класс конструктор, а то, имеет ли класс какие-либо виртуальные методы. Для получения подробной информации, Google для Vtable и Vptr.

...