C++

스마트 포인터 - shared_ptr

monstro 2024. 5. 27. 01:59
728x90
반응형

너무 오랜만에 포스팅을 하게 되어 죄송합니다.

그동안 개인적인 사정으로 잠시 포스팅을 멈추게 되었습니다.

일이 잘 해결되어 이제 다시 포스팅을 시작하겠습니다.

 

1) 스마트 포인터란?

이름에서 알 수 있듯이, 스마트 포인터는 기존의 포인터에 포인터를 관리하는 추가적인 요소들을 섞어주는 것을 말합니다.

즉, 일반적인 포인터보다 더 많은 역할을 수행하는 포인터를 스마트 포인터라고 할 수 있습니다.

그리고 현대의 C++에서는 포인터를 사용하기보다는 스마트 포인터를 사용할 것을 권장합니다.

이는 C++ 기반의 게임 엔진인 언리얼 엔진도 마찬가지인데,

언리얼 엔진에서는 C++을 사용할 때는 스마트 포인터를, 언리얼 C++에서는 가비지 컬렉터를 사용합니다.

 

그렇다면, 왜 스마트 포인터를 사용하는 것일까요?

그것은 포인터의 한계에 있습니다.

 

위와 같은 클래스가 존재한다고 가정하겠습니다

 

다음의 연산을 거치게 되면

 

위와 같은 연산 결과가 나오게 됩니다

 

 

p2는 delete되어 더 이상 존재하지 않는 상태가 되었지만,

p1의 포인터는 그것을 인식하지 못하고 p2를 참조하게 됩니다.

다시 말해, 일반적인 포인터포인터가 참조하고 있는 대상이 살아있는지 여부를 판단하기가 힘듭니다.

 

그리고 이 점에서 일반적인 포인터가 가지고 있는 위험한 점이 드러납니다.

delete된 메모리 주소가 아닌 엉뚱한 메모리의 주소를 참조하게 되어 메모리 오염을 일으키게 됩니다.

 

이런 이유로 현대의 C++은 스마트 포인터의 사용을 권장합니다.

 

2) 스마트 포인터 - shared_ptr

스마트 포인터는 크게 3가지로 분류할 수 있습니다.

 

  • shared_ptr
  • weak_ptr
  • unique_ptr

그리고 이번 포스팅에서는 shared_ptr을 설명드리겠습니다.

 

shared_ptr은 내부적으로 refCount를 사용하여 가리키는 대상의 참조 횟수를 기록합니다.

refCount가 0이 되면 자동적으로 delete를 하게 되고, 참조 횟수가 증가하거나 감소하면 그만큼 refCount를 가감합니다.

 

클래스 구조의 변형

 

다음의 연산을 거치게 되면
위와 같은 결과를 얻을 수 있습니다

 

이렇듯, shared_ptr은 내부적으로 refCount를 집계하여 포인터의 참조 대상이 살아있는지 여부를 알 수 있습니다.

그리고 shared_ptr을 통해 메모리를 더 안전하게 사용할 수 있습니다.

 

3) shared_ptr의 추가적인 정보

위의 코드에서 볼 수 있듯이, shard_ptr에 대해서는 추가적인 규칙이 존재합니다.

 

첫번째로, 한번 shared_ptr로 사용되었다면 그 이후에도 shared_ptr로 사용해야 합니다.

TargetPtr로 지정하기 위해 Player를 참조하는 shared_ptr을 만들어주었습니다.

 

두번째로, shared_ptr은 소멸 시점을 조정해줄 수 없습니다.

refCount가 0이 되지 않는 이상 소멸시킬 수 없으므로, 자유로운 소멸이 힘들다는 단점이 존재합니다.

 

세번째로, shared_ptr을 매개변수로 넘기는 경우 &(참조연산자)를 통한 참조를 넘겨주는 것이 좋습니다.

복사 방식을 사용하는 경우, refCount를 1 증가하고 구문이 끝나면 다시 1 감소하는 연산에 대한 시간이 소모됩니다.

따라서 매개변수로 넘기는 경우에는 &를 통해 원본을 넘김으로써 불필요한 연산을 줄이는 것이 좋습니다.

 

마지막으로, refCount은 Thread_Safety가 보장됩니다.

Thread_Safety가 보장된다는 것은 여러 스레드가 동시에 접근해도 프로그램의 실행에 문제가 없음을 의미합니다.

즉, 여러 스레드가 동시에 접근하여 한번에 무수히 많은 refCount의 증가가 이루어지지 않는다는 것입니다.

그 이유는 refCount가 atomic_int의 데이터 타입을 지니기 때문인데,

간단히 말해 스레드끼리의 데이터 경합이 일어나지 않는 데이터 타입임을 의미합니다.

 

이번 포스팅을 통해 shared_ptr에 대해 알아볼 수 있었습니다.

다음에는 나머지 스마트 포인터인 weak_ptr과 unique_ptr에 대해 알아보겠습니다.

728x90
반응형

'C++' 카테고리의 다른 글

자료구조 - 연결 리스트  (0) 2024.08.18
스마트 포인터 - weak_ptr, unique_ptr  (0) 2024.05.27
동적할당  (0) 2024.04.29
iterator(반복자)  (0) 2024.04.29
오른값 참조  (0) 2024.04.22