1. 스택 기반 객체 생성
int main() {
Car myCar;
myCar.StartCar();
return 0;
}
특징
- 메모리 할당 위치:
- 객체 myCar는 스택(stack)에 생성된다.
- main 함수가 종료되면 스택 메모리에서 자동으로 해제된다.
- 수명:
- myCar는 생성된 함수(여기서는 main)의 스코프(scope) 내에서만 존재한다.
- 스코프를 벗어나면 객체가 자동으로 소멸되므로 delete가 필요하지 않다.
- 성능:
- 스택 할당은 힙 할당보다 빠르며 오버헤드가 적다.
- 안정성:
- 메모리 누수가 발생하지 않으며, 개발자가 별도로 메모리를 해제할 필요가 없어 안전하다.
2. 힙 기반 객체 생성
int main() {
Car* myCar = new Car();
myCar->StartCar();
delete myCar; // 메모리 해제 필수
return 0;
}
특징
- 메모리 할당 위치:
- 객체 myCar는 힙(heap)에 생성된다.
- new 키워드로 동적 할당된 메모리는 개발자가 명시적으로 delete로 해제해야 한다.
- 수명:
- myCar는 개발자가 명시적으로 delete를 호출할 때까지 존재한다.
- 따라서 스코프를 벗어나도 소멸하지 않고 메모리에 남아있을 수 있다.
- 성능:
- 힙 할당은 스택 할당보다 느리며, 힙 관리에 추가 비용이 발생한다.
- 안정성:
- delete를 호출하지 않으면 메모리 누수가 발생한다.
- 잘못된 포인터 접근(예: delete 이후 객체 접근)으로 프로그램이 예기치 않게 동작할 수 있다.
차이점 요약
특징 | 스택 기반 | 힙 기반 |
메모리 위치 | 스택 | 힙 |
수명 | 스코프가 끝나면 자동 소멸 | 명시적으로 해제 필요 |
성능 | 빠름 | 느림 |
메모리 관리 | 자동 관리 (안전) | 개발자가 수동으로 관리 |
사용 예시 | 지역 변수나 임시 객체 | 긴 수명, 큰 객체, 다형성 필요 |
언제 힙 할당을 사용하는가?
- 수명이 스코프를 초과하는 객체가 필요할 때:
- 예: 함수 내부에서 생성된 객체를 함수 외부에서도 사용해야 할 때.
- 크기가 큰 객체를 사용할 때:
- 스택은 크기가 제한되어 있으므로, 큰 객체는 힙에 할당하는 것이 안전하다.
- 다형성을 사용할 때:
- 힙 기반으로 생성하면 부모 클래스 포인터를 통해 자식 클래스 객체를 참조할 수 있다.
Car* car = new SportsCar(); // Car는 부모 클래스, SportsCar는 자식 클래스 car->Drive(); delete car;
결론
- 스택 기반 객체 생성은 더 간단하고 안전하며, 메모리 관리가 자동으로 이루어져 기본적으로 선호된다.
- 하지만 객체의 수명이 스코프를 초과하거나 다형성이 필요한 경우에는 힙 기반 할당을 사용하고, 그에 따른 메모리 관리에 주의를 기울여야 한다.
메모리 관리를 더 쉽게 하고 싶다면, C++의 스마트 포인터(예: std::unique_ptr, std::shared_ptr)를 사용하는 것이 좋은 방법이다.
#include <memory>
using namespace std;
int main() {
unique_ptr<Car> myCar = make_unique<Car>();
myCar->StartCar();
// 메모리가 자동으로 해제됨
return 0;
}