返回

智能指针深入理解:TSharedPtr、TSharedRef、TWeakPtr、FName与UObject

前端

前言

智能指针是 C++ 中的一种内存管理技术,用于管理堆内存。智能指针可以自动释放它指向的对象,从而避免了内存泄漏和悬空指针等问题。UE4 中提供了多种智能指针,包括 TSharedPtr、TSharedRef、TWeakPtr、FName 和 UObject。本文将深入讲解这些智能指针的使用、相互转换以及注意事项,旨在为 UE4 游戏开发人员提供更加深入和全面的智能指针知识,有助于提升代码质量和避免常见的陷阱。

TSharedPtr

TSharedPtr 是 UE4 中最常用的智能指针。它是一个模板类,可以指向任何类型的对象。TSharedPtr 的用法与普通指针非常相似,但是它可以自动释放它指向的对象。

TSharedPtr<MyClass> myObject = MakeShareable<MyClass>();

上面的代码创建一个指向 MyClass 对象的 TSharedPtr。MakeShareable() 函数创建一个新的 MyClass 对象,并将其包装在一个 TSharedPtr 中。

TSharedPtr 可以通过引用计数来管理对象的生命周期。当一个 TSharedPtr 被创建时,对象的引用计数为 1。当一个 TSharedPtr 被复制时,对象的引用计数会增加。当一个 TSharedPtr 被销毁时,对象的引用计数会减少。当对象的引用计数为 0 时,对象将被自动释放。

TSharedRef

TSharedRef 是另一个常用的智能指针。它也是一个模板类,可以指向任何类型的对象。TSharedRef 与 TSharedPtr 的主要区别在于,TSharedRef 始终指向一个有效的对象。也就是说,TSharedRef 永远不会指向一个空指针。

TSharedRef<MyClass> myObject = MakeShareable<MyClass>();

上面的代码创建一个指向 MyClass 对象的 TSharedRef。MakeShareable() 函数创建一个新的 MyClass 对象,并将其包装在一个 TSharedRef 中。

TSharedRef 可以通过引用计数来管理对象的生命周期。当一个 TSharedRef 被创建时,对象的引用计数为 1。当一个 TSharedRef 被复制时,对象的引用计数会增加。当一个 TSharedRef 被销毁时,对象的引用计数会减少。当对象的引用计数为 0 时,对象将被自动释放。

TWeakPtr

TWeakPtr 是一个弱智能指针。它是一个模板类,可以指向任何类型的对象。TWeakPtr 与 TSharedPtr 和 TSharedRef 的主要区别在于,TWeakPtr 不会增加它指向的对象的引用计数。也就是说,当一个 TWeakPtr 被创建时,对象的引用计数不会改变。

TWeakPtr<MyClass> myObject = MakeWeakPtr(mySharedPtr);

上面的代码创建一个指向 MyClass 对象的 TWeakPtr。MakeWeakPtr() 函数创建一个新的 TWeakPtr,并将其指向由 mySharedPtr 指向的对象。

TWeakPtr 不会增加它指向的对象的引用计数,因此它不会影响对象的生命周期。当对象被销毁时,TWeakPtr 将指向一个空指针。

FName

FName 是 UE4 中一种特殊的智能指针。它用于管理字符串。FName 是一个不可变的字符串,这意味着它一旦被创建,就不能被修改。FName 可以通过名称或哈希值来创建。

FName myName = FName(TEXT("MyName"));

上面的代码创建一个名为 "MyName" 的 FName。

FName myName = FName(12345);

上面的代码创建一个具有哈希值 12345 的 FName。

FName 可以通过名称或哈希值来比较。

if (myName == FName(TEXT("MyName"))) {
  // Do something
}

上面的代码检查 myName 是否等于 "MyName"。

if (myName == FName(12345)) {
  // Do something
}

上面的代码检查 myName 是否具有哈希值 12345。

UObject

UObject 是 UE4 中的一种特殊智能指针。它用于管理 UObject 对象。UObject 是 UE4 中所有对象的基类。UObject 可以通过名称或对象指针来创建。

UObject* myObject = NewObject<UObject>();

上面的代码创建一个新的 UObject 对象。

UObject* myObject = FindObject<UObject>(nullptr, TEXT("MyObject"));

上面的代码通过名称查找一个 UObject 对象。

UObject 可以通过名称或对象指针来访问其属性和方法。

myObject->GetFName();

上面的代码获取 myObject 的 FName 属性。

myObject->CallFunction();

上面的代码调用 myObject 的 CallFunction() 方法。

智能指针的相互转换

TSharedPtr、TSharedRef 和 TWeakPtr 可以相互转换。

TSharedPtr<MyClass> mySharedPtr = MakeShareable<MyClass>();
TSharedRef<MyClass> mySharedRef = mySharedPtr.ToSharedRef();
TWeakPtr<MyClass> myWeakPtr = mySharedPtr.ToWeakPtr();

上面的代码将一个 TSharedPtr 转换为一个 TSharedRef 和一个 TWeakPtr。

TSharedRef<MyClass> mySharedRef = MakeShareable<MyClass>();
TSharedPtr<MyClass> mySharedPtr = mySharedRef.AsShared();
TWeakPtr<MyClass> myWeakPtr = mySharedRef.ToWeakPtr();

上面的代码将一个 TSharedRef 转换为一个 TSharedPtr 和一个 TWeakPtr。

TWeakPtr<MyClass> myWeakPtr = MakeWeakPtr(mySharedPtr);
TSharedPtr<MyClass> mySharedPtr = myWeakPtr.Pin();
TSharedRef<MyClass> mySharedRef = myWeakPtr.ToSharedRef();

上面的代码将一个 TWeakPtr 转换为一个 TSharedPtr 和一个 TSharedRef。

智能指针的注意事项

在使用智能指针时,需要注意以下几点:

  • 避免循环引用。循环引用是指两个或多个对象相互引用,导致引用计数无法降为 0,从而导致内存泄漏。
  • 避免使用空指针。空指针是指向一个不存在的对象的指针。使用空指针可能会导致程序崩溃。
  • 正确使用智能指针的相互转换。智能指针的相互转换可能会导致内存泄漏或悬空指针。

结论

智能指针是 C++ 中一种非常有用的内存管理技术。UE4 中提供了多种智能指针,包括 TSharedPtr、TSharedRef、TWeakPtr、FName 和 UObject。这些智能指针可以帮助我们避免内存泄漏和悬空指针等问题。通过了解智能指针的基本概念及其在 UE4 中的应用,我们可以编写出更加健壮和可靠的代码。