[CPP 03~05] class, inheritance memory address
CPP Module 03을 평가를 받으면서 기존에 끝낸 @jaewkim 이후 과제에서도 알아두어야 한다! 이야기한 Class 의 메모리 영역 및 구성이 어떻게 되었길래 사이즈가 이렇게 나오는 지 포스트를 새로 하고자 한다.
주소값을 보게 되면 CPP Module에서 파생 클래스의 생성자가 발생될 때 기초 클래스가 불려진 후, 파생 클래스가 불려지는 지 추측을 해보게 됩니다. (사진2 참고, 각 생성자에 문구를 입력 시 기초 클래스가 먼저 출력되며 소멸자는 역으로 파생 클래스가 먼저 출력)
image 1 을 통해서 보게되면 기초(부모) 클래스의 첫 번째 멤버 변수를 시작으로 파생(자식) 클래스 마지막 멤버 변수로 주소가 이어지는 것을 확인 할 수 있습니다.
해당 rosa 라는 인스턴스(객체)의 주소는 첫 번째 멤버 변수의 주소입니다.
위 image 3 에서는 모든 멤버 변수가 int 로 되어 있지만, 이제 멤버 변수 타입을 변경해 보도록 하겠습니다.
클래스 메모리 크기는 멤버 중 제일 큰 변수의 메모리를 기준으로 레이아웃을 잡아나갑니다.
레이아웃마다 제일 큰 공간으로 잡아 잡아 메모리 낭비가 심해 programa pack 으로 1 byte로 할당할 수 있습니다.
double이 제일 메모리가 큰 변수 이기 때문에 8바이트가 기준이 됩니다. image 4에서 첫 번째 줄은 첫 멤버 변수 int 가 들어가고도 4바이트가 남기에 short가 차지하게 됩니다. 그러므로 Cat class의 사이즈는 24가 됩니다.
조금의 이해를 돕기 위해 참고 사이트의 이미지를 들고 왔습니다.
// #1 test : 24byte
class Test1
{
short a;
int b;
char c;
double d;
}
// #2 test : 16byte
class Test2
{
short a;
char b;
int c;
double d;
}
가상 함수를 가진 클래스는 멤버 변수 이외의 가상 함수 리스트(vtable)을 가리키는 포인터 vfptr를 가집니다. (클래스 할당 시 제일 앞부분에 포인터 (4byte)로 할당하며, 가장 큰 메모리의 공간을 멤버 변수와 별개로 잡습니다)
class Animal {
public:
int _type;
virtual void print() {
std::cout << "Hello\n";
}
protected:
short _color;
};
class Cat: public Animal {
public:
int _age;
void print() {
std::cout << "world!\n";
}
private:
std::string _name;
};
int main() {
Cat alo;
printf("Animal sizeof\t: %lu\n", sizeof(Cat));
}
print 되는 Cat의 크기는 몇 일까?
정답 : 48
제일 큰 변수는 24이지만 8바이트로 측정 되는 거 같다.
sizeof(virtual function) : 4 => 8
int + short => 8
short => 8
sizeof(string) : 24 => 24
+= 48
Class member가 저장되는 영역
메모리 구조는 코드, 데이터, 스택, 힙 영역으로 나뉩니다.
- 코드 영역 : 실행할 프로그램의 코드가 저장되는 영역으로 텍스트 영역
- 데이터 영역 : 프로그램의 전역 변수와 정적(static) 변수가 저장되는 영역
- 스택 영역 : 함수의 호출과 관계되는 지역 변수와 매개변수가 저장되는 영역
함수의 호출과 함께 할당 되며함수의 호출이 완료되면 소멸 - 힙 영역 : 사용자가 직접 관리할 수 있는 '그리고 해야만 하는' 메모리 영역
비정적 멤버 변수는 스택 영역에 저장
정적 멤버 변수는 데이터 영역에 저장
멤버 함수는 코드 영역에 저장