Notice
Recent Posts
Recent Comments
Link
삶의 공유
C++ 스마트 포인터(Smart Pointer) 완전 정리 본문
728x90
반응형
📘 C++ 스마트 포인터(Smart Pointer) 완전 정리
현대 C++에서 **스마트 포인터(Smart Pointer)**는 자원 관리(Resource Management)를 단순화하고, 안전하게 만드는 핵심 기능입니다. 이 글에서는 스마트 포인터의 원리부터, 직접 구현 예제, 그리고 표준 라이브러리에서 제공하는 스마트 포인터까지 정리해보겠습니다.
1. 스마트 포인터란?
포인터처럼 동작하는 객체
스마트 포인터는 일반 포인터의 역할을 하면서도 객체이기 때문에
- 생성자
- 소멸자
- 복사/대입/이동 연산자
등의 과정을 통해 다양한 추가 작업을 자동으로 수행할 수 있습니다.
특히 소멸자에서 자원 해제를 보장하기 때문에,
new 로 생성한 객체를 직접 delete 하지 않아도 됩니다.
2. 스마트 포인터의 원리
핵심은 바로 연산자 오버로딩입니다.
template <typename T>
class Ptr {
T* obj{};
public:
explicit Ptr(T* p = nullptr) : obj{p} {}
~Ptr() { delete obj; } // 자동 delete
T* operator->() { return obj; }
T& operator*() { return *obj; }
};
- operator->() : 내부 포인터 반환 → p->go() 같은 문법 지원
- operator*() : 내부 객체 참조 반환 → (*p).go() 같은 문법 지원
즉,
Ptr<Car> p(new Car);
p->go(); // (p.operator->())->go();
(*p).go(); // (p.operator*()).go();
이렇게 포인터처럼 자연스럽게 사용할 수 있습니다.
3. 왜 Raw Pointer 대신 Smart Pointer?
Car* p = new Car;
// ... 사용 ...
delete p; // 직접 해제해야 함
- delete 를 깜빡하면 메모리 누수 발생
- 예외나 조기 return 으로 delete를 놓치면 문제 심각
- 여러 포인터가 같은 객체를 가리키면 이중 delete 위험
Ptr<Car> p(new Car);
// 스코프 종료 시 ~Ptr() 자동 호출 → delete obj
👉 RAII(Resource Acquisition Is Initialization) 원칙에 따라 객체 생명주기에 맞춰 자원 해제가 자동으로 이루어집니다.
4. 주의사항
- operator*() 는 반드시 참조(T&) 를 반환해야 합니다.
- 값으로 반환하면 임시 객체가 만들어져 원본과 달라지는 문제가 생길 수 있습니다.
- operator->() 는 보통 원시 포인터(T)* 를 반환해야 합니다.
- 그렇지 않으면 체이닝에서 문제가 발생할 수 있습니다.
- nullptr 상태일 때 *p 또는 p-> 호출 → UB(정의되지 않은 동작)
- 필요하다면 assert 등을 걸어 디버깅 보조.
5. 표준 스마트 포인터
C++ 표준은 <memory> 헤더에서 3가지 스마트 포인터를 제공합니다.
5.1 std::unique_ptr<T>
- 단독 소유 (unique ownership)
- 복사 불가, 이동만 가능
- 가장 가볍고 안전한 스마트 포인터
auto p = std::make_unique<Car>();
p->go();
5.2 std::shared_ptr<T>
- 여러 곳에서 소유 (shared ownership)
- 참조 카운트(reference count) 로 관리
- 마지막 하나가 파괴될 때 자원 해제
std::shared_ptr<Car> p1 = std::make_shared<Car>();
std::shared_ptr<Car> p2 = p1; // 참조 카운트 증가
5.3 std::weak_ptr<T>
- shared_ptr의 보조 포인터 (비소유)
- 참조 카운트에는 영향을 주지 않음
- lock() 으로 shared_ptr 변환 후 사용 가능
- 순환 참조(cyclic reference) 문제 방지
6. Shallow Copy 문제와 스마트 포인터
- 클래스에 포인터 멤버가 있다면, 디폴트 복사 생성자는 단순히 주소만 복사(얕은 복사) 합니다.
- 그 결과 두 객체가 같은 메모리를 가리켜 이중 delete 문제가 생깁니다.
- 해결책:
- 깊은 복사(Deep Copy) – 메모리 새로 할당 후 내용 복사
- 참조 카운팅(Reference Counting) – shared_ptr
- 소유권 이전(Move Semantics) – unique_ptr
- 복사 금지(Delete) – 자원 유일 소유만 허용
👉 스마트 포인터는 이런 문제를 자동으로 해결해 주는 도구입니다.
7. 정리
- 스마트 포인터 = 포인터 역할을 하는 객체
- 핵심 원리 = ->, * 연산자 오버로딩 + 소멸자에서 자원 해제
- 장점
- 자원 관리 자동화 → 메모리 누수 방지
- 예외 안전성 보장
- 소유권 모델(unique, shared, weak) 명확
- 실무에서는 직접 구현보다 표준 스마트 포인터 사용이 권장됩니다.
📌 한 줄 요약
스마트 포인터는 “포인터처럼 보이지만 자원 관리까지 책임지는 객체”이다.
RAII 원칙을 지키며 안전하고 현대적인 C++ 코드를 작성할 수 있게 도와준다.
반응형
'Programing언어 > C++' 카테고리의 다른 글
| C++ ADL (Argument Dependent Lookup) 완벽 정리 (0) | 2025.10.15 |
|---|---|
| C++ 함수 객체(Function Object) 완전 정리 (0) | 2025.09.29 |
| [C++] Null Ptr (널포인터) 기본 다지기 (1) | 2024.02.17 |
| [C++] Const, Return, Rvalue - Reference (1) | 2024.02.06 |
| [C++] Reference (1) | 2024.02.03 |