📌 언리얼 엔진에서 TSharedPtr 사용 예제
TSharedPtr은 스마트 포인터(Smart Pointer) 로, 객체의 참조 카운트를 자동으로 관리해줘.
즉, 객체를 여러 개의 포인터가 공유할 수 있으며, 마지막 포인터가 소멸되면 자동으로 메모리가 해제됨.
✅ TSharedPtr의 특징
자동 메모리 관리
참조하는 포인터가 하나도 없으면 객체가 자동으로 삭제됨.
안전한 메모리 해제
delete를 직접 호출할 필요가 없음.
객체 공유 가능
여러 개의 TSharedPtr이 하나의 객체를 참조할 수 있음.
✅ TSharedPtr 기본 사용법
🎯 1️⃣ 기본적인 생성 및 사용
#include "CoreMinimal.h"
// 스마트 포인터를 이용한 클래스 정의
class FMyClass
{
public:
FMyClass() { UE_LOG(LogTemp, Warning, TEXT("FMyClass 생성됨")); }
~FMyClass() { UE_LOG(LogTemp, Warning, TEXT("FMyClass 삭제됨")); }
void PrintMessage()
{
UE_LOG(LogTemp, Warning, TEXT("Hello from FMyClass!"));
}
};
// TSharedPtr 사용 예제
void UseSharedPtr()
{
// 새로운 FMyClass 객체를 TSharedPtr로 생성
TSharedPtr SharedPtr = MakeShared();
// 스마트 포인터로 함수 호출
SharedPtr->PrintMessage();
// SharedPtr이 범위를 벗어나면 자동으로 객체가 삭제됨
}
📌 MakeShared() 를 이용하면 안전하게 TSharedPtr 생성 가능!
→ new 키워드 대신 MakeShared를 사용해야 함.
🎯 2️⃣ 여러 개의 TSharedPtr이 같은 객체를 참조하는 경우
void SharedPtrExample()
{
// FMyClass 객체를 스마트 포인터로 생성
TSharedPtr PtrA = MakeShared();
{
// PtrA를 PtrB에 복사 (참조 카운트 증가)
TSharedPtr<FMyClass> PtrB = PtrA;
UE_LOG(LogTemp, Warning, TEXT("PtrB가 PtrA를 공유 중!"));
}
// 여기서 PtrB가 사라졌지만 PtrA가 남아있으므로 객체는 삭제되지 않음.
UE_LOG(LogTemp, Warning, TEXT("PtrB가 범위를 벗어남!"));
}
// PtrA가 범위를 벗어나면 객체가 삭제됨!
📌 PtrA와 PtrB가 같은 객체를 공유하고 있기 때문에 참조 카운트가 증가하고, PtrB가 사라져도 객체는 삭제되지 않음.
→ 하지만 PtrA가 범위를 벗어나면 객체는 자동 삭제됨.
🎯 3️⃣ TSharedPtr을 함수에 전달하는 방법
void PrintSharedPtrMessage(TSharedPtr InPtr)
{
if (InPtr.IsValid()) // 포인터가 유효한지 확인
{
InPtr->PrintMessage();
}
}
void ExampleFunction()
{
TSharedPtr Ptr = MakeShared();
PrintSharedPtrMessage(Ptr); // 포인터를 함수로 전달
}
📌 IsValid() 함수를 사용하면 포인터가 유효한지 확인 가능!
🎯 4️⃣ TWeakPtr와 함께 사용하기 (TSharedPtr의 단점 해결)
📌 TSharedPtr은 참조 카운트가 0이 될 때까지 객체가 메모리에 남음
→ 순환 참조(Circular Reference) 문제 발생 가능
→ 해결 방법: TWeakPtr 사용!
class FMyClass
{
public:
void PrintMessage() { UE_LOG(LogTemp, Warning, TEXT("Hello from FMyClass!")); }
};
void WeakPtrExample()
{
TSharedPtr SharedPtr = MakeShared();
// TWeakPtr을 사용하여 참조 카운트 증가 없이 공유
TWeakPtr<FMyClass> WeakPtr = SharedPtr;
if (TSharedPtr<FMyClass> SafePtr = WeakPtr.Pin()) // 안전하게 변환
{
SafePtr->PrintMessage();
}
}
📌 WeakPtr.Pin()을 사용하면 TSharedPtr로 변환 가능!
→ 객체가 삭제되었는지도 확인 가능하므로 순환 참조 문제를 방지할 수 있음.
✅ 최종 정리
스마트 포인터 유형 설명 사용 예
TSharedPtr 참조 카운트를 증가시키며, 마지막 포인터가 삭제되면 객체 삭제 여러 개의 포인터가 같은 객체를 공유할 때
TWeakPtr 참조 카운트를 증가시키지 않음. TSharedPtr이 존재하는 동안만 객체에 접근 가능 순환 참조를 방지할 때
📌 TSharedPtr은 안전한 메모리 관리를 제공하지만, 순환 참조 문제를 조심해야 함
📌 객체를 공유해야 하면 TSharedPtr, 순환 참조를 방지하려면 TWeakPtr을 사용하면 됨. 🚀