核心思想:程序员只管分配堆内存,释放内存交给智能指针。UE有自己的一套内存管理系统,但这只针对与UObject。为了方便对非UObject对象的内存管理,UE设计了一套自己智能指针库。包含:共享指针(TSharedPtr)、弱指针(TWeakPtr)、以及特有的共享硬引用(TSharedRef)。
首先需要创建一个类
class TestA
{
public:
int a = 0;
float b = 0;
TestA()
{
a = 0;
b = 0;
};
TestA(int a, float b)
{
this->a = a;
this->b = b;
};
~TestA()
{
UE_LOG(LogTemp, Warning, TEXT("xiguo"));
}
private:
};
下面声明三个函数,分别用于测试不同的内容
//测试共享指针
void TestAFunc();
//测试共享应用
void TestBFunc();
//测试弱指针
//弱指针能解决循环引用,只对引用对象保留引用权,不参与引用计
//不能阻止对象被销毁,如果弱指针指向的对象被销毁则弱指针会自动清空
void TestCFunc();
TestAFunc()
void AMySmartPtrActor::TestAFunc()
{
//C++中创建指针
TestA* ptr1 = new TestA(1, 2.0f);
//共享指针左值初始化
TSharedPtr<TestA>Sharedptr2(ptr1);//不推荐这种方式,容易混淆共享指针和原生指针
ptr1 = nullptr;
//共享指针右值初始化
TSharedPtr<TestA>Sharedptr3(new TestA(3, 4.0f));
//拷贝构造函数初始化
TSharedPtr<TestA>Sharedptr4(Sharedptr2);
//UE的方法初始化共享指针
TSharedPtr<TestA>Sharedptr5 = nullptr;//共享指针可以初始化为空
Sharedptr5 = MakeShareable(new TestA(5, 6.0f));
//线程安全的共享指针
TSharedPtr<TestA, ESPMode::ThreadSafe>Sharedptr6(new TestA(7, 8.0f));
//共享指针常用的接口
if (Sharedptr5.IsValid())//判断指针是否指向了一个有效的对象
{
TSharedRef<TestA>SharedRef1(new TestA(9,10.0f));
//共享指针转为共享引用,引用计数加一
SharedRef1 = Sharedptr5.ToSharedRef();
//获得引用计数
int32 Count1 = Sharedptr5.GetSharedReferenceCount();
//这里为2,是MakeShareable还有SharedRef1,一共两个类对象共享同一指针
UE_LOG(LogTemp, Warning, TEXT("Count is %d"), Count1);
if (!Sharedptr5.IsUnique())
{
UE_LOG(LogTemp, Warning, TEXT("sharedptr5 is not Unique"));
}
//Get的作用是解引用,返回引用对象的原生指针
Sharedptr5.Get()->a;
UE_LOG(LogTemp, Warning, TEXT("Shareptr5a is %d"), Sharedptr5.Get()->a);
//重置共享指针
Sharedptr5.Reset();
int32 Count2 = Sharedptr5.GetSharedReferenceCount();
UE_LOG(LogTemp, Warning, TEXT("Count is %d"), Count2);
}
}
TestBfunc()
void AMySmartPtrActor::TestBFunc()
{
//共享引用初始化的时候必须指向一个有效的对象
TSharedRef<TestA>SharedRef2(new TestA(7, 8.0f));
if (SharedRef2.IsUnique())//
{
SharedRef2->a;//虽然是共享引用,但是解引用的方式仍然是->
UE_LOG(LogTemp, Warning, TEXT("SharedRef2a is %d"), SharedRef2->a);
TSharedPtr<TestA>Sharedptr6;
//共享引用转换为共享指针,可以直接转化
Sharedptr6 = SharedRef2;
//解引用
Sharedptr6.Get()->b;
UE_LOG(LogTemp, Warning, TEXT("Sharedptr6b is %f"), Sharedptr6.Get()->b);
}
}
TestCFunc()
void AMySmartPtrActor::TestCFunc()
{
//测试弱指针
//弱指针能解决循环引用,只对引用对象保留引用权,不参与引用计
//不能阻止对象被销毁,如果弱指针指向的对象被销毁则弱指针会自动清空
TSharedPtr<TestA>Sharedptr7 = MakeShareable(new TestA(10, 11.0f));
TSharedRef<TestA>SharedRef3(new TestA(12, 13.0f));
//声明弱指针并初始化
TWeakPtr<TestA>WeakPtr1(Sharedptr7);
TWeakPtr<TestA>WeakPtr2(SharedRef3);
if (WeakPtr1.IsValid())
{
//弱指针如何转换为共享指针
TSharedPtr<TestA>Sharedptr8(WeakPtr1.Pin());
if (Sharedptr8.IsValid())
{
Sharedptr8.Get()->a;
UE_LOG(LogTemp, Warning, TEXT("Sharedptr8a is %d"), Sharedptr8.Get()->a);
}
}
}
要记得在BeginPlay里面使用
void AMySmartPtrActor::BeginPlay()
{
Super::BeginPlay();
//TestAFunc();
//TestBFunc();
TestCFunc();
}