Nagie's DevStory
[CPP] 38. 스마트 포인터 (Smart pointer) 본문
스마트 포인터는 동적으로 할당된 메모리를 관리하고 해제하는 데 도움을 주는 기능 중 하나다.
기존의 포인터는 동적 메모리를 사용할 때 new와 delete로 직접 관리를 해줘야 했지만
스마트 포인터를 사용하면 타 언어의 GC랑 유사하게 동작한다.
스마트 포인터의 종류는 3가지이며 <memory>헤더에 정의되어 있다.
그러면 각각의 스마트 포인터에 대해 알아보겠다.
1. shared_ptr
이름에서부터 어떤 목적으로 사용되는지 감이 오는 이 포인터는
여러 스마트 포인터가 같은 메모리 리소스를 공유할 수 있으며 리소스에 대한 참조 횟수를 추적하고, 참조 횟수가 0이 되면
자동으로 메모리 해제를 한다. 'shared_ptr'은 동적으로 할당된 메모리가 여러 객체를 참조할 때 유용하게 사용할 수 있다.
#include <memory>
int main() {
std::shared_ptr<int> ptr = std::make_shared<int>(42);
std::shared_ptr<int> copy = ptr; // 복사 가능
// 메모리는 자동으로 해제됨
}
2. unique_ptr
오직 하나의 스마트 포인터만이 특정 메모리 리소스를 소유한다.
다른 스마트 포인터나 일반 포인터로부터 이동 또는 전달이 가능하지만 소유권은 항상 하나의 'unique_ptr'만 가질 수 있다.
#include <memory>
int main() {
std::unique_ptr<int> ptr = std::make_unique<int>(42);
std::unique_ptr<int> moved = std::move(ptr); // 이동 가능
// 메모리는 자동으로 해제됨
}
3. weak_ptr
주로 순환 참조(Circular reference) 문제를 해결하기 위해 사용된다.
'shared_ptr'과 함께 사용되며, 리소스를 참조하지만, 참조 횟수에 영향을 주지 않는다.
따라서 순환 참조 문제를 방지하면서 해당 리소스에 접근할 수 있다.
#include <memory>
int main() {
std::shared_ptr<int> shared = std::make_shared<int>(42);
std::weak_ptr<int> weak = shared;
// shared_ptr를 통해 리소스에 접근
if (std::shared_ptr<int> temp = weak.lock()) {
// temp를 통해 리소스 사용
}
// weak_ptr는 리소스 해제에 영향을 주지 않음
}
여기 까진 C++ 11 이후에 추가된 스마트 포인터지만
최초의 C++ 표준안(C++98)부터 살아남아 있는 'auto_ptr'이(가) 있는데 이건 사용하지 않는 걸 권장한다.
C++ 11 이전 레거시 코드를 다룬다면 선택권이 없겠지만 C++ 11 이후 환경에선 쓰지 않는 게 정신건강에 이롭다.
특히 'auto_ptr'이(가) 가지는 문제점은 소유권 이전 문제와 복사 시 안정성을 보장할 수 없는 문제
또 배열과 함께 사용 불가능하다는 문제점이 있다.
//auto_ptr의 사용예시
std::auto_ptr<int> ptr1(new int(42));
std::auto_ptr<int> ptr2 = ptr1; // 소유권 이전, ptr1은 이후 무효화됨
//무효화 이후의 동작을 예측할 수 없음...