Pages

Thursday, July 23, 2009

C++ классы: размещение в памяти. Часть I.

Маленький ребенок разломал игрушку. Родители возмущены - такая красивая игрушка... ай-я-яй..., столько денег стоила,... А деточка хотел узнать как эта штука устроена, хотел подправить кое-что, усовершенствовать даже.
С++ не игрушка, но тоже хочется понять как это устроено. Ломать не будем. Просто посмотрим и назад положим. Никто и не заметит, что трогали.
Вот классы - это как раз то, что эти плюсы (С++) к названию языка добавило - есть, просто С. А с классами - С++. То, что это абстракция всем понятно. И как работать с этой абстракцией тоже понятно. Вот эту абстракцию на байты и разберем.
Я должен уточнить, что я работаю с Microsoft Visual Studio 2005 и поэтому все программы приведенные в статье сделаны для компилятора Microsoft. Больше того – я допускаю, что и само распределение памяти для объектов классов может быть организовано по-другому в других компиляторах.
#include <stdio.h>
class CEmpty
{
};
int main()
{
CEmpty empty;
printf("size of CEmpty object is %d\r\n", sizeof(empty));
return 0;
}

В этой программе создан объект "пустого" класса т определяется его размер - это 1 байт. Должен же быть у объекта какой-то размер. Именно так и определяется стандартом языка. Если такой класс наследуется, тот же стандарт позволяет компиляторам "удалять" такие пустые классы в процессе оптимизации.
Добавим частную переменную целого типа в класс:

#include <stdio.h>
class CNotEmpty
{
int x;
};
int main()
{
CNotEmpty empty;
printf("size of CNotEmpty object is %d\r\n", sizeof(empty));
return 0;
}


Размер стал 4 байта. Добавим еще одну переменную типа int:

#include <stdio.h>
class CNotEmpty
{
int x;
int y;
};
int main()
{
CNotEmpty empty;
printf("size of CNotEmpty object is %d\r\n", sizeof(empty));
return 0;
}


Размер 8 байт:

С третьей переменной целого типа будет 12:

Добавим метод:

#include <stdio.h>
class CNotEmpty
{
int x;
int y;
int z;
public:
void method()
{
printf("method\r\n");
}
};
int main()
{
CNotEmpty empty;
printf("size of CNotEmpty object is %d\r\n", sizeof(empty));
empty.method();
return 0;
}


Размер не меняется:

Проверим другие типы переменных:

#include <stdio.h>
class CInt
{
int x;
int y;
int z;
public:
void method()
{
printf("method\r\n");
}
};
class CDouble
{
double x;
public:
void method()
{
printf("method\r\n");
}
};
class CChar
{
char x;
public:
void method()
{
printf("method\r\n");
}
};
class CCharArray
{
char x[24];
public:
void method()
{
printf("method\r\n");
}
};
int main()
{
CInt objInt;
printf("size of CInt object is %d\r\n", sizeof(objInt));
CDouble objDouble;
printf("size of CDouble object is %d\r\n", sizeof(objDouble));
CChar objChar;
printf("size of CChar object is %d\r\n", sizeof(objChar));
CCharArray objCharArray;
printf("size of CCharArray object is %d\r\n", sizeof(objCharArray));
return 0;
}



Размер объекта это сумма размеров его переменных. Объект, если рассматривать его с точки зрения управления памятью - это объединение памяти переменных класса. Это только промежуточный вывод и он будет уточнен и детализирован позже. Дело в том, что я не упоминал в каком порядке эти переменные расположены, как наследование и полиморфизм влияют на распределения памяти для объектов.

No comments:

Post a Comment