概念

共享指针(Shared Pointers) 是指既健壮、又能为空指针的智能指针。共享指针沿袭了普通智能指针的所有优点,它能避免出现内存泄漏、悬挂指针,还能避免指针指向未初始化的内存。但它们还有一些其他特点,例如:

  • 共享所有权(Shared Ownership): 引用计数支持多个共享指针,以确保它们引用的数据对象永远不被删除,前提是它们中的任意一个仍指向数据对象。
  • 自动失效(Automatic Invalidation): 你可安全引用易变对象,无需担心出现悬挂指针。
  • 弱引用: 弱指针可中断引用循环。
  • 意向指示(Indication of Intent): 区分拥有者(参见共享引用)和观察者,并提供不可为空的引用。

共享指针有一些值得注意的基本特性,包括:

  • 语法非常健壮
  • 非侵入式(但能反射)
  • 线程安全(视情况而定)
  • 性能佳,占用内存少

  • 共享引用 是一类强大且不可为空的 智能指针,其被用于引擎的 Uobject 系统外的数据对象。此意味无法重置共享引用、向其指定空对象,或创建空白引用。因此共享引用固定包含有效对象,甚至未拥有 IsValid 方法。在共享引用和 [共享指针](Shared Pointers) 间选择时,除非需要空白或可为空的对象,否则共享引用为优先选项。如需可能空白或可为空的引用,则应使用共享指针。

注意:与标准的C++引用不同,可在创建后将共享引用重新指定到另一对象。依我看,本质来说,引用是一种特殊的指针。

线程安全

线程安全的声明如下,不写则为不安全

  1. TSharedPtr<NormalClass,ESPMode::ThreadSafe> NormalSharedPtr(new NormalClass(TEXT( FUNCTION )));

测试代码

头文件

  1. // Fill out your copyright notice in the Description page of Project Settings.
  2. #pragma once
  3. #include "CoreMinimal.h"
  4. #include "UObject/NoExportTypes.h"
  5. #include "MyObject.generated.h"
  6. /**
  7. *
  8. */
  9. //用宏声明2个参数的委托,返回值int32
  10. DECLARE_DELEGATE_RetVal_TwoParams(int32, FTestDelegateTwoparamsRetVal, float, const FString&);
  11. UCLASS(Blueprintable)
  12. class TESTCPP_API UMyObject : public UObject
  13. {
  14. GENERATED_BODY()
  15. public:
  16. UMyObject();
  17. UPROPERTY(BlueprintReadWrite)
  18. float value = 15;
  19. UFUNCTION(BlueprintCallable)
  20. void myfunction();
  21. UFUNCTION(BlueprintCallable)
  22. int32 testDelegatefuction(float a, const FString& s);//声明被委托的函数
  23. UFUNCTION(BlueprintCallable)
  24. void testfuntion();
  25. UFUNCTION(BlueprintCallable)
  26. void testRef();
  27. UFUNCTION(BlueprintCallable)
  28. void tranform();
  29. FTestDelegateTwoparamsRetVal myDelegate;//声明一个委托对象
  30. };
  31. class Fmyclass {
  32. public:
  33. Fmyclass() { UE_LOG(LogTemp, Warning, TEXT("Hellow Fmyclass")); }
  34. void testFun() { UE_LOG(LogTemp, Warning, TEXT("Test Fmyclass")); }
  35. ~Fmyclass() { UE_LOG(LogTemp, Warning, TEXT("Dead Fmyclass")); };
  36. };

实现

  1. // Fill out your copyright notice in the Description page of Project Settings.
  2. #include <string.h>
  3. #include "MyObject.h"
  4. UMyObject::UMyObject() {
  5. }
  6. void UMyObject::myfunction()
  7. {
  8. UE_LOG(LogTemp, Warning, TEXT("Hellow World"));
  9. GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, FString::Printf(TEXT("value = %d"), value));
  10. //实现绑定
  11. myDelegate.BindUObject(this, &UMyObject::testDelegatefuction);
  12. //判断是否绑定成功,避免崩溃
  13. if (myDelegate.IsBound())
  14. myDelegate.Execute(23, "Hi");
  15. }
  16. int32 UMyObject::testDelegatefuction(float a, const FString& s)
  17. {
  18. return int32(a);
  19. }
  20. void UMyObject::testfuntion()
  21. {
  22. //创建一个共享指针对象
  23. TSharedPtr<Fmyclass> testptr = MakeShareable(new Fmyclass());
  24. //判断有效性,并调用成员函数
  25. if (testptr.IsValid())
  26. {
  27. testptr->testFun();
  28. }
  29. //获取指针计数
  30. int32 count = testptr.GetSharedReferenceCount();
  31. UE_LOG(LogTemp, Warning, TEXT("Count=%d"), count);
  32. //手动解引用,不写也可以,离开本作用域消亡
  33. testptr.Reset();
  34. }
  35. void UMyObject::testRef()
  36. {
  37. //创建共享引用,两种写法
  38. TSharedRef<Fmyclass> testref = MakeShareable(new Fmyclass);
  39. TSharedRef<Fmyclass> testref2(testref);
  40. //获取引用计数
  41. int32 count = testref.GetSharedReferenceCount();
  42. //返回CPP类对象
  43. testref.Get();
  44. //调用成员函数
  45. testref2->testFun();
  46. //判断是唯一引用
  47. if (testref.IsUnique()){
  48. UE_LOG(LogTemp, Warning, TEXT("isUniqueRef"));
  49. }
  50. }
  51. void UMyObject::tranform()
  52. {
  53. // 共享引用转化成共享指针
  54. TSharedRef<Fmyclass> TestRef = MakeShareable(new Fmyclass);
  55. TSharedPtr<Fmyclass> TestPtr = TestRef;
  56. //共享指针转化成共享引用
  57. TSharedPtr<Fmyclass>TestPtr2 = MakeShareable(new Fmyclass);
  58. TSharedRef<Fmyclass>TestRef2 = TestPtr2.ToSharedRef();
  59. }

测试结果

image.png