概念
共享指针(Shared Pointers) 是指既健壮、又能为空指针的智能指针。共享指针沿袭了普通智能指针的所有优点,它能避免出现内存泄漏、悬挂指针,还能避免指针指向未初始化的内存。但它们还有一些其他特点,例如:
- 共享所有权(Shared Ownership): 引用计数支持多个共享指针,以确保它们引用的数据对象永远不被删除,前提是它们中的任意一个仍指向数据对象。
- 自动失效(Automatic Invalidation): 你可安全引用易变对象,无需担心出现悬挂指针。
- 弱引用: 弱指针可中断引用循环。
- 意向指示(Indication of Intent): 区分拥有者(参见共享引用)和观察者,并提供不可为空的引用。
共享指针有一些值得注意的基本特性,包括:
- 语法非常健壮
- 非侵入式(但能反射)
- 线程安全(视情况而定)
性能佳,占用内存少
共享引用 是一类强大且不可为空的 智能指针,其被用于引擎的 Uobject 系统外的数据对象。此意味无法重置共享引用、向其指定空对象,或创建空白引用。因此共享引用固定包含有效对象,甚至未拥有 IsValid 方法。在共享引用和 [共享指针](Shared Pointers) 间选择时,除非需要空白或可为空的对象,否则共享引用为优先选项。如需可能空白或可为空的引用,则应使用共享指针。
注意:与标准的C++引用不同,可在创建后将共享引用重新指定到另一对象。依我看,本质来说,引用是一种特殊的指针。
线程安全
线程安全的声明如下,不写则为不安全
TSharedPtr<NormalClass,ESPMode::ThreadSafe> NormalSharedPtr(new NormalClass(TEXT( FUNCTION )));
测试代码
头文件
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "MyObject.generated.h"
/**
*
*/
//用宏声明2个参数的委托,返回值int32
DECLARE_DELEGATE_RetVal_TwoParams(int32, FTestDelegateTwoparamsRetVal, float, const FString&);
UCLASS(Blueprintable)
class TESTCPP_API UMyObject : public UObject
{
GENERATED_BODY()
public:
UMyObject();
UPROPERTY(BlueprintReadWrite)
float value = 15;
UFUNCTION(BlueprintCallable)
void myfunction();
UFUNCTION(BlueprintCallable)
int32 testDelegatefuction(float a, const FString& s);//声明被委托的函数
UFUNCTION(BlueprintCallable)
void testfuntion();
UFUNCTION(BlueprintCallable)
void testRef();
UFUNCTION(BlueprintCallable)
void tranform();
FTestDelegateTwoparamsRetVal myDelegate;//声明一个委托对象
};
class Fmyclass {
public:
Fmyclass() { UE_LOG(LogTemp, Warning, TEXT("Hellow Fmyclass")); }
void testFun() { UE_LOG(LogTemp, Warning, TEXT("Test Fmyclass")); }
~Fmyclass() { UE_LOG(LogTemp, Warning, TEXT("Dead Fmyclass")); };
};
实现
// Fill out your copyright notice in the Description page of Project Settings.
#include <string.h>
#include "MyObject.h"
UMyObject::UMyObject() {
}
void UMyObject::myfunction()
{
UE_LOG(LogTemp, Warning, TEXT("Hellow World"));
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, FString::Printf(TEXT("value = %d"), value));
//实现绑定
myDelegate.BindUObject(this, &UMyObject::testDelegatefuction);
//判断是否绑定成功,避免崩溃
if (myDelegate.IsBound())
myDelegate.Execute(23, "Hi");
}
int32 UMyObject::testDelegatefuction(float a, const FString& s)
{
return int32(a);
}
void UMyObject::testfuntion()
{
//创建一个共享指针对象
TSharedPtr<Fmyclass> testptr = MakeShareable(new Fmyclass());
//判断有效性,并调用成员函数
if (testptr.IsValid())
{
testptr->testFun();
}
//获取指针计数
int32 count = testptr.GetSharedReferenceCount();
UE_LOG(LogTemp, Warning, TEXT("Count=%d"), count);
//手动解引用,不写也可以,离开本作用域消亡
testptr.Reset();
}
void UMyObject::testRef()
{
//创建共享引用,两种写法
TSharedRef<Fmyclass> testref = MakeShareable(new Fmyclass);
TSharedRef<Fmyclass> testref2(testref);
//获取引用计数
int32 count = testref.GetSharedReferenceCount();
//返回CPP类对象
testref.Get();
//调用成员函数
testref2->testFun();
//判断是唯一引用
if (testref.IsUnique()){
UE_LOG(LogTemp, Warning, TEXT("isUniqueRef"));
}
}
void UMyObject::tranform()
{
// 共享引用转化成共享指针
TSharedRef<Fmyclass> TestRef = MakeShareable(new Fmyclass);
TSharedPtr<Fmyclass> TestPtr = TestRef;
//共享指针转化成共享引用
TSharedPtr<Fmyclass>TestPtr2 = MakeShareable(new Fmyclass);
TSharedRef<Fmyclass>TestRef2 = TestPtr2.ToSharedRef();
}