개발/C, C++

스마트 포인터

토레로르 2023. 11. 30. 16:56

스마트 포인터(Smart Pointer)

 

스마트 포인터란 C++에서 동적으로 할당된 메모리를 관리하는데 사용되는 포인터의 래퍼 클래스이다. 스마트 포인터는 시스템이 종료될 때 자동으로 메모리를 해제함으로 프로그램의 안정성을 높여준다.

 

스마트 포인터의 종류

std::unique_ptr

한 객체에 대한 소유권을 가지며, 해당 객체를 다른 스마트 포인터와 공유할 수 없다. 복사 및 할당이 불가능하며, 소유권을 이전(std::move)하는 것만 가능하다.

 

std::shared_ptr

여러 스마트 포인터가 같은 객체를 공유할 수 있도록 하는 스마트 포인터이다. 내부적으로는 참조 횟수를 사용하여 객체의 소유권을 다룬다. 모든 std::shared_ptr이 소멸되면(참조 횟수가 0이 되면) 객체가 자동으로 메모리에서 해제된다.

 

std::weak_ptr

std::shared_ptr과 함께 사용되어, 순환 참조를 방지하는데 사용된다. std::weak_ptr은 소유권을 가지지 않고, 객체를 참조할 때 참조 횟수를 증감시키지 않는다.

 

std::weak_ptr은 std::shared_ptr이나 다른 std::weak_ptr의 자원으로부터 복사 생성자나 대입 연산자를 통해 자원을 할당받는다.

 

 

std::shared_ptr 의 문제와 해결방안

순환참조

두 개의 std::shared_ptr이 서로를 참조하는 경우, 메모리가 해제되지 않을 수 있다.

 

해결법 : std::weak_ptr을 사용하여 약한 참조를 구성한다.

 

메모리 오버헤드

std::shared_ptr은 객체의 메모리 뿐만 아니라, 참조 횟수 정보도 추적하기 위해 control block이라고 하는 추가적인 메모리를 사용한다. 이 control block에는 메모리 주소, 참조 횟수 등이 저장된다.

 

해결법 : std::unique_ptr은 단일 소유자만을 허용하기에, 참조 횟수 추적과 control block이 필요하지 않다. 적절한 상황에는 std::shared_ptr 대신 std::unique_ptr을 사용하도록 한다.

 

스레드 측면

std::shared_ptr로 여러 스레드간에 객체가 공유될 때, 의도치 않은 문제가 발생할 수 있다. 대표적으로는 동시 접근이나, 순환 참조, 공유 불가와 같은 문제가 있다.

 

해결법 1 : std::atomic<std::shared_ptr<T>>을 사용해 원자적 연산을 할 수 있도록 사용.

해결법 2 : std::mutex를 사용해 스레드간 동기화 사용.