E) Class Memory structure

1. Empty Class
#include <cstdio>
class Empty{};
int main(void){
Empty inst;
printf("sizeof(inst)==%lu\n", sizeof(inst));
return 0;
}

sizeof(inst)==1

Empty* pa=new Empty();
Empty* pb=new Empty();
위와 같은 경우, 만일 빈 클래스가 0 바이트 메모리를 할당한다면, heap의 사용 증가가 없기 때문에,
pa와 pb에 같은 메모리가 저장되게 된다. 이를 방지하기 위해 빈 클래스도 1바이틀 차지한다.
2. 필드를 가진 클래스
class FieldSample{
char ch1;
}; // 1바이트
class FieldSample{
char ch1;
char ch2;
}; // 2바이트
class FieldSample{
char ch1;
int n1;
char ch2;
}; // ch1, ch2에 각각 4바이트씩 할당되어 총 12바이트 차지
#pragma pack(1) // 1바이트 정렬
class FieldSample{
public:
char ch1;
int n1;
char ch2;
}; // ch1, ch2에 각각 1바이트씩 할당되어 총 6바이트 차지
3. 멤버함수를 가진 단일 클래스
함수는 메모리에 변화를 주지않는다.(함수는 코드 영역에 별도로 저장되고, static 변수는 전역 변수 공간에 저장)
virtual function의 경우, virtual function table(vtable)이 생성되어 포인터를 하나 필요로 함
#include <cstdio>
class FieldFuncSample{
public:
int n1=1;
void func1(){}
};
class FieldFuncSample_v{
public:
int n1=1;
void func1(){}
virtual void vfunc1(){}
};
int main(void){
FieldFuncSample inst;
FieldFuncSample_v inst_v;
printf("sizeof(inst)==%lu\n", sizeof(inst));
printf("sizeof(inst_v)==%lu\n", sizeof(inst_v));
return 0;
}

sizeof(inst)==4

sizeof(inst_v)==16

내부적으로 64비트 컴퓨터는 포인터에 8바이트를 사용하며, 필드로 인해 int(4바이트) 또한 8바이트 공간 차지
4. 단일 상속 클래스
#include <cstdio>
class A{
public:
int n1=1;
void func1(){ n1++; }
virtual void vfunc1() {}
};
class BonA: A{
public:
int n2=2;
void func2(){ n2++; }
virtual void vfunc2() {}
};
class ConBonA: BonA{
public:
int n3=2;
void func3(){ n3++; }
};
int main(void){
BonA inst;
ConBonA inst2;
printf("sizeof(inst)==%lu\n", sizeof(inst));
printf("sizeof(inst2)==%lu\n", sizeof(inst2));
return 0;
}

sizeof(inst)==16

sizeof(inst2)==24

클래스를 상속 받을 때,
메모리는 vtable을 가장 아래에 할당하고, 이후에 Base Class 멤버부터, Derived Class 멤버순으로 할당한다.
(vtable은 상속받은 개체에는 기록되지 않는다.)
5. 단일 상속 클래스의 형 변환
위와 같은 순서로 데이터가 저장되기 때문에, 단순히 부모클래스 포인터에 자식 클래스의 주소값을 대입해도
해당 범위(부모클래스)까지만 읽는다.
ConBonA* pInst=new ConBonA();
BonA* pbInst=(BonA*)pInst;
A* paInst=(A*)pInst;
00B71B8E  mov         eax, [new로 할당받은 힙 주소]
00B71B9B  mov         dword ptr [ebp-34h],eax  // pInst 변수에 ConBonA* 타입의 this 포인터 보관

        BonA *pbInst = (BonA *)pInst;
00B71BB1  mov         dword ptr [ebp-40h],eax  // pbInst 변수에 BonA* 타입의 this 포인터 보관

        A *paInst = (A *)pInst;
00B71BB7  mov         dword ptr [ebp-4Ch],eax  // paInst 변수에 A* 타입의 this 포인터 보관
https://www.sysnet.pe.kr/2/0/11164