Unreal Engine

[UE]스마트 포인터

programmer-faust 2025. 8. 29. 01:50
  • 순서
    1. 스마트 포인터란?
    2. 스마트 포인터의 계열과 종류
    3. 스마트 포인터 사용시 장단점
  • 스마트 포인터란?
    1. 포인터처럼 동작하지만, 단순한 주소 값 저장 외에 메모리 관리나 안정성 보장을 추가로 해주는 객체
    2. 스마트 포인터는 RAII 원칙을 적용해서, 포인터가 더 이상 필요 없어질 때 자동으로 자원을 해제 해줌.
  • 스마트 포인터의 계열과 종류
    1. Non-UObject 계열: UObject가 아닌 일반 클래스/구조체에 사용
      • TUniquePtr<T>
        1. C++의 unique_ptr과 동일
        2. 단일 소유권, 복사 불가, 이동만 가능함
        3. 범위를 벗어나면 자동 삭제됨
      • TSharedPtr<T>
        1. 참조 카운트 기반
        2. 마지막 참조가 해제될 때 객체가 삭제됨
        3. MakeShared<T>()로 생성
      • TWeakPtr<T>
        1. TSharedPtr에서 약한 참조
        2. 대상이 살아있는지 확인 가능(Pin()을 호출해서 유효하면 TSharedPtr 반환함)
    2. UObject 계열: UObject는 엔진의 GC가 생존 여부를 결정하기 때문에, 일반 포인터 대신 GC-aware 포인터를 사용해야 함
      • TWeakObjectPtr<UObjectType>
        1. UObject에 대한 안전한 약한 참조
        2. 객체가 GC에 의해 파괴되면 자동으로 nullptr로 무효화됨
        3. Raw 포인터는 GC가 모른 채 객체를 날려버릴 수 있어 위험하여 해당 보인터를 써야 안전함.
      • TSoftObjectPtr<UObjectType>
        1. 에디터/런타임에서 Asset 경로 기반의 참조
        2. 실제 객체가 메모리에 로드되어 있지 않아도 경로로 추적 가능함
        3. 필요할 때 LoadSynchronous()나 AsyncLoad로 불러옴
        4. 리소스 지연 로딩(Lazy Loading) 구현에 많이 사용됨
      • FWeakObjectPtr
        1. TWeakObjectPtr의 비템플릿 버전으로 내부용이며 직접적으로 잘 사용하지는 않음
  • 스마트 포인터 사용시 장단점
    1. 장점
      • 자동 메모리 관리(RAII)
        1. 범위를 벗어나거나 참조 카운트가 0이 되면 자동으로 delete > 메모리 누수 방지
        2. 예외 상황에서도 안전하게 자원이 해제됨
      • 안전성 증가
        1. 잘못된 delete 방지
        2. dangling pointer 위험 감소
        3. 특히 weak_ptr, TWeakObjectPtr같은 약한 참조는 유효성 체크가 가능해서 안전성 강화
      • 가독성 및 유지보수성
        1. 코드에서 delete를 직접 쓰지 않으므로 관리 부담 감소.
        2. 협업 시 포인터의 소유권 정책을 명시적으로 표현 가능.
      • 예외 안전성
        1. 함수 실행 중 예외가 발생하더라도 소멸자가 호출되면서 자원이 정리됨.
        2. 리소스 누락 방지.
    2. 단점
      • 성능 오버헤드
        1. shared_ptr은 참조 카운트를 증가/감소해야 하므로, 원시 포인터 보다 느림.
        2. weak_ptr도 lock 과정에서 추가 비용이 있음.
        3. 언리얼의 TSharedPtr도 마찬가지로 참조 카운트 연산이 비용 발생.
      • 순환 참조 문제
        1. shared_ptr이 서로를 가리키면 참조 카운트가 0이 되지 않아 메모리 누수가 발생.
        2. 이를 해결하려면 반드시 weak_ptr을 적절히 섞어 써야 함.
      • 메모리 사용량 증가
        1. 참조 카운트, 제어 블록 등 추가 메타데이터를 저장해야 해서 메모리 사용량이 증가.
        2. 원시 포인터에 비해 메모리 overhead 존재.
      • 소유권 모델 이해 필요
        1. 단순히 new/delete만 아는 개발자보다 더 복잡한 개념을 알아야 함.
        2. 잘못 쓰면 오히려 관리가 더 어려워짐.
      • GC와 혼용 시 주의 필요
        1. 언리얼은 자체 GC가 있는데, UObject*를 TSharedPtr로 관리하면 GC가 객체를 모를 수 있음.
        2. 그래서 언리얼에서는 TWeakObjectPtr, TSoftObjectPtr 같은 GC-aware 스마트포인터를 따로 제공

'Unreal Engine' 카테고리의 다른 글

[UE]StaticClass와 GetClass  (0) 2025.08.29
[UE] 언리얼 빌드 툴/헤더 툴  (0) 2025.08.29
[UE] 언리얼 엔진의 GC  (1) 2025.08.28
[UE] 언리얼의 클래스들  (0) 2025.08.28
[UE]언리얼 오브젝트  (0) 2025.08.28