스마트 포인터의 개념
스마트 포인터는 C++ 11에서 도입된 기능으로, 동적으로 할당된 메모리를 자동으로 관리해주는 객체입니다.
기존의 생 포인터(raw pointer)가 가진 여러 문제점들을 해결하기 위해 설계되었습니다.
스마트 포인터의 주요 장점
- 메모리 누수 방지
- 댕글링 포인터(dangling pointer) 문제 해결
- 예외 발생 시에도 안전한 리소스 해제
- 소유권 개념의 명확한 표현
스마트 포인터는 <memory> 헤더에 정의되어 있습니다.
스마트 포인터에는 다음과 같은 종류가 있습니다.
- std::unique_ptr
- std::shared_ptr
- std::weak_ptr
std::unique_ptr
std::unique_ptr은 특정 객체에 대한 유일한 소유권을 가지는 스마트 포인터입니다.
주요 특징
- 복사할 수 없음 (이동은 가능)
- 포인터가 범위를 벗어나면 자동으로 메모리 해제
- 배열 형태의 메모리도 관리 가능
- 커스텀 삭제자(deleter) 지정 가능
std::shared_ptr
std::shared_ptr은 여러 포인터가 하나의 객체를 공유할 수 있게 해주는 스마트 포인터입니다.
주요 특징
- 참조 횟수(reference count)를 통해 객체의 수명 관리
- 마지막 shared_ptr이 소멸될 때 객체 삭제
- 순환 참조 문제 발생 가능 (weak_ptr로 해결)
std::weak_ptr
std::weak_ptr은 std::shared_ptr이 관리하는 객체에 대한 약한 참조를 제공합니다.
주요 특징
- 참조 횟수를 증가시키지 않음
- 순환 참조 문제 해결에 사용
- 객체의 존재 여부 확인 가능
스마트 포인터의 사용 지침
- 가능한 한 생 포인터 대신 스마트 포인터를 사용하세요.
- 객체에 대한 단독 소유권이 필요할 때는 std::unique_ptr을 사용하세요.
- 여러 곳에서 객체를 공유해야 할 때만 std::shared_ptr을 사용하세요.
- 순환 참조를 피하기 위해 std::weak_ptr을 사용하세요.
- 스마트 포인터 생성 시 std::make_unique와 std::make_shared를 사용하세요.
실습
- 다음 코드를 스마트 포인터를 사용하여 메모리 누수를 방지하도록 수정하세요.
- std::shared_ptr을 사용하여 간단한 그래프 구조를 구현하세요. 노드 클래스는 다른 노드에 대한 포인터를 여러 개 가질 수 있어야 합니다.
- 위의 그래프 구조에서 발생할 수 있는 순환 참조 문제를 std::weak_ptr을 사용하여 해결하세요.
참고자료
- Effective Modern C++ by Scott Meyers
- C++ Core Guidelines
- cppreference.com - Smart pointers
- "Back to Basics : Smart Pointers" - CppCon 2019 presentation by Rainer Grimm