TIL

[C++]객체 지향과 메모리 관리

think95592 2026. 5. 4. 20:57

1. 추상 클래스는 객체를 생성할 수 없다 추상 클래스는 일종의 미완성 설계도다. 클래스 내부에 virtual void attack() = 0;과 같은 순수 가상 함수가 하나라도 포함되면, Player p;처럼 직접 객체를 생성하는 것이 불가능하다. 이는 반드시 해당 설계도를 상속받은 자식 클래스를 통해서만 실체를 만들 수 있음을 의미한다. 자식 클래스에게 특정 기능을 반드시 구현하도록 강제하는 가이드라인 역할을 한다.

2. 순환 참조는 전방 선언으로 해결한다 Player.h와 Monster.h가 서로를 인클루드하면 컴파일러가 무한 루프에 빠져 에러를 발생시킨다. 이를 막기 위해서는 헤더 파일에서 #include를 사용하는 대신, class Monster;와 같이 이름만 미리 알려주는 '전방 선언'을 활용해야 한다. 객체의 상세한 설계 내용은 실제 구현 파일인 .cpp에서 인클루드하여 참조하는 것이 정석이다.

3. 동적 할당과 메모리 관리의 중요성 new 키워드로 메모리를 빌려오면 그 주소값인 포인터를 통해 객체를 관리하게 된다. 하지만 사용이 끝난 후 delete를 해주지 않으면 메모리 누수(Memory Leak)가 발생한다. 빌린 메모리를 제때 반납하지 않으면 시스템 자원이 낭비되어 게임이 버벅거리거나 강제 종료되는 치명적인 원인이 되므로 주의가 필요하다.

4. 스마트 포인터의 활용 (shared, weak, auto) 수동으로 delete를 관리하는 위험을 줄이기 위해 스마트 포인터를 사용한다. shared_ptr는 객체의 소유권을 공유하며 참조 카운트가 0이 될 때 자동으로 메모리를 해제한다. 반면 weak_ptr는 객체를 소유하지 않고 관찰만 하기에, lock() 함수로 객체의 생사 여부를 확인한 뒤 안전하게 접근할 수 있다. 여기에 auto를 곁들이면 복잡한 포인터 타입을 일일이 명시하지 않아도 되어 코드가 간결해진다.

5. 생성자와 포인터의 명확한 역할 차이 생성자는 객체가 메모리에 할당될 때 이름이나 능력치 같은 초기 상태를 세팅하는 역할을 수행한다. new를 통해 포인터로 주소를 할당받든 일반 변수로 선언하든, 객체가 생성되는 시점에는 반드시 생성자가 호출되어 내부 값을 채우게 된다. 즉, 포인터는 주소를 담는 '그릇'이고 생성자는 그 안의 '내용물'을 채우는 작업이다.