정적할당 : 시작할때 특정 공간을 먼저 만들고 시작합니다 !
대표적인 예시로 배열이 있는데, int a[10]의 경우에 10개의 공간을 먼저 스택메모리에 만들어놓습니다.
미리 공간을 만들어 놓는다면 이점도 있겠지만 다음 예시를 본다면 단점도 있다는 것을 알게 될것입니다.
만약에 손님을 받을 배열을 10개만 만들었는데, 불경기로인해 손님이 1명씩만 꾸준하게 온다면
남는 9개의 공간은 계속 낭비가 되어야합니다 ㅠㅠㅠ
그래서 나온 개념이 동적할당 입니다 ! 동적할당은 프로그램 실행 중에도 필요한 크기의 메모리를
운영체제에 요청하여 사용할 수 있는 방법으로 사용 예시는 다음과 같습니다 .
int *p = new int;
인트 포인터형식의 p를 선언하고
new라는 키워드를 붙여서 int형식으로 동적할당합니다.
또, 동적할당은 힙이라는 메모리 영역에 존재합니다 !
하지만 동적할당은 !!!!! 가장중요!!!!!!!!!!!
할당된 메모리가 필요없는 시점에 delete 키워드로 반드시반드시!!
직접해제 해야합니다.
그 이유는 스택과 힙메모리의 특성때문에 그렇습니다 . 좀 더 자세하게 알아보겠습니다 .
스택 : 함수의 매개변수나 지역 변수처럼 대부분의 일반변수는 스택이라는 메모리 영역에 할당됩니다.
스택영역은 함수의 호출과 함께 할당되며 함수가 반환되면 자동으로 소멸합니다.
하지만 일반적으로 스택영역은 메모리 크기가 한정되어 있기 때문에 이 크기를 초과하는 프로그램일 경우 운영체제가 프로그램을 강제적으로 종료합니다 .
힙 : 동적으로 할당된 변수는 힙이라는 메모리 영역에 존재하며 힙은 스택보다 훨씬 큰 메모리 용량을 가지고 있어, 크기가 큰 배열도 할당할 수 있습니다. 힙에 할당된 메모리는 프로그램이 종료될때까지 계속 유지가 되는 특성이 있습니다.
따라서 우리는 힙에 할당된 메모리 다시말해 유저경험이 일어나는 그 소중한 공간의 메모리를 확보해야만합니다
그래서 힙에 할당된 메모리는 명시적으로 delete 키워드를 통해 해제를 하여야합니다
다시 클래스의 개념으로 돌아가겠습니다.
예시를 동물로 들겠습니다. 동물 제각각 울음소리는 다를것입니다.
편의상 염소는 음메, 소는 음무, 고양이는 야옹입니다.
하지만 이들 사이에는 공통점이 있습니다 ! 울음소리를 낸다는 것입니다.
만약에 다형성이라는 개념을 모른상태로 염소와 소와 고양이와 낙타와 뱀 ...(etc)
등의 울음소리를 구현하려고하면.. 생각만해도 아찔합니다. 분명 우리는 낮과 밤을 새야할것입니다
그래서 나온 개념이 다형성이라고 생각합니다..!!
c++에서 다형성을 구현할 때 멤버 함수 가운데
자식 클래스에서 오버라이딩(다시말해 재정의) 해야하는 함수는
가상함수로 선언해야합니다. 일반 멤버 함수도 자식클래스에서
오버라이딩 할 수 있지만, 가상함수로 선언해야 하는 이유는
부모클래스로 업캐스팅 되었을 때 호출되는 함수에 차이가 있기 때문입니다.
업캐스팅이란 자식 클래스를 부모 클래스 형식으로 변환하는 것을 말하며 업캐스팅은 자동으로 이루어집니다.
일밤 멤버함수는 업캐스팅된 부모클래스에 구현된 함수가 호출되지만
가상 함수는 자식 클래스에서 오버라이딩한 함수가 호출됩니다.
이러한 특징덕분에 자식들이 부모의 함수를 가지고
여러가지의 형태를 지니게 되는 다형성을 구현할 수 있는것입니다.
또, 실제 호출할 시 파생 클래스를 확인하라는 의미에서
virtual을 붙입니다 !
지금부터 예시를 보겠습니다.
class Animal {
public:
Animal() {
cout << "Animal생성자" << endl;
}
virtual void makeSound()=0;
~Animal() {
cout << "Animal소멸자" << endl;
}
};
class Dog : public Animal {
public:
Dog() {
cout << "Dog생성자" << endl;
}
void makeSound() {
cout << "Dog" << endl;
}
~Dog() {
cout << "Dog소멸자" << endl;
}
};
위의 사진에서처럼 부모의 virtual makeSound(); 를 통해 가상함수임을 알리고,
밑의 class Dog : public Animal {} 에서 makeSound를 재정의 했음을 알 수 있습니다.
여기서 저는 2가지가 궁금하였습니다.
1. 왜 virtual makeSound()=0; 인가?
==>순수가상함수 : 동물마다 울음소리는 반드시 존재해야만 합니다 !!
그래서 우리는 반드시 존재하는 함수를 자녀클래스에서 재정의(오버라이딩) 할 때 이 MakeSound라는것을 빼먹지 말라는 의미에서 =0이라는 순수가상함수를 이용했습니다.
순수가상함수란 부모클래스에서 구현한 함수를 반드시! 자녀클래스에서 재정의 해야만합니다.
쉽게 설명해서 부모클래스에서 makeSound라는건 0이다 다시말해 없다!
하지만 이 개념은 반드시 존재해야하니깐..나의 자식들아 부탁해 ..이런 느낌인것 같습니다.
2. class Dog : Public Animal
==> 해당의 문법은 접근지정자를 통해 애니멀이라는 부모클래스로부터 Dog가 상속받고 있습니다.
하지만 Public이라는 키워드를 쓰지 않는다면 컴파일러는 자동으로 Private로 인식해
우리는 Dog클래스를 자유자재로 사용할 수 없을 것입니다.
따라서 Public을 통해 자유자재로 사용할 수 있게 합니다 !
끝으로 매우매우매우매우매우 중요한 내용을 공부하여서 이 공부한 내용을 공유하고 오늘의 TIL은 마치겠습니다.
<동적할당과 정적할당시 생성자>
다음과 같은 Animal과 Animal을 상속받은 Dog클래스의 생성자가 있다고 가정해보겠습니다 !
class Animal {
public:
Animal() {
cout << "Animal생성자" << endl;
}
virtual void makeSound()=0;
~Animal() {
cout << "Animal소멸자" << endl;
}
};
class Dog : public Animal {
public:
Dog() {
cout << "Dog생성자" << endl;
}
void makeSound() {
cout << "Dog" << endl;
}
~Dog() {
cout << "Dog소멸자" << endl;
}
};
main함수에서 다음과 같은 2가지를 실행해보겠습니다.
int main(){
cout << "정적할당 시작합니다 " << endl;
Dog a;
cout << "동적할당 시작합니다 " << endl;
Animal* b;
cout << "Start " << endl;
b = new Dog();
cout << "delete 시작합니다" << endl;
delete b;
cout << "정적 할당 자동 delete 예정" << endl;
return 0;
}
위의 코드를 실행시켜보면 다음과 같은 결과값을 얻을 수 있습니다.

여기서 엄청난 사실들을 매우매우 매우 많이 알 수 있습니다 !
1-1 정적할당 선언시 ! 위에 Dog a; 라고 정적할당으로 Dog클래스를 선언하였습니다.
이 경우 정적할당은 반드시 기본생성자를 실행하여야합니다. 그래서 정적할당 시작합니다 라는 출력 이후에 바로
Animal생성자->Dog생성자가 출력된 것입니다.
잠시 2일전의 내용을 복습하자면 , 자식클래스가 생성될 때의 순서는 부모클래스 생성-> 자식클래스 생성입니다 !
따라서 정적할당을 할 경우 !!! 반드시 클래스내에 기본생성자가 존재하여야합니다
1-2 동적할당 선언시 ! 위에 Animal *b; 라는 동적할당을 할 공간을 먼저 만들었습니다 !
위의 정적할당과는 다르게 동적할당할 공간을 만들 때, 생성자가 실행되지 않습니다.
Start라는 출력이후에 동적으로 할당을 해주었을 때만 생성자가 실행함을 알 수 있습니다
2-1 해제시 동적할당 : delete 키워드를 통해 동적할당을 해제하였습니다. 그 후에 바로 Animal 형식의 할당이 해제된것을 알 수 있습니다.
2-2 delete시 동적할당 : return 0; 이전에 저는 정적할당이 자동으로 할당이 해제되는것을 보여드리기 위해
출력함수를 집어넣었고, main이라는 함수 내에서 함수가 끝남과 동시에 정적할당한 Dog a가 해제됨을 알 수 있습니다.
여기서도 2일전의 복습을 해보자면 소멸할때는 자식->부모 순으로 소멸하게 됩니다.
'TIL' 카테고리의 다른 글
TIL : 2024 /12/30 : new[]와 new 의 차이 (1) | 2024.12.30 |
---|---|
2024/12/27 TIL : 오버로딩과 오버라이딩 (1) | 2024.12.27 |
2024/12/24 TIL : 생성자 (3) | 2024.12.24 |
2024 /12/23 TIL : c++ 클래스 문법 (0) | 2024.12.23 |
2024/12/18 TIL : 블루프린트로 게임 로직 만들어보기 ! (2) | 2024.12.18 |