UE_C++ —— UE反射系统(二)
目录一Properties二UFunctions三Metadata Specifiers四Unreal Smart Pointer Library一PropertiesProperties 属性使用标准的C变量语法声明前面用UPROPERTY宏来定义属性变量的说明符和元数据UPROPERTY([specifier, specifier, ...], [meta(key value, key value, ...)]) Type VariableName;核心数据类型// Integers uint8、uint16、uint32、uint64 int8、int16、int32、int64 As Bitmasks // 元标记可使整数作为下拉列表形式可供编辑/*~ BasicBits appears as a list of generic flags in the editor, instead of an integer field. */ UPROPERTY(EditAnywhere, Meta (Bitmask)) int32 BasicBits;/*~ You can set MyFunction using a generic list of flags instead of typing in an integer value. */ UFUNCTION(BlueprintCallable) void MyFunction(UPARAM(meta (Bitmask)) int32 BasicBitsParam)//自定义bitflags名称 UENUM(Meta (Bitflags)) enum class EColorBits { ECB_Red, ECB_Green, ECB_Blue };//将定义好的枚举转化为bitmask UENUM(Meta (Bitflags, UseEnumValuesAsMaskValuesInEditor true)) enum class EColorBits { ECB_Red 0x01, ECB_Green 0x02, ECB_Blue 0x04 }; ENUM_CLASS_FLAGS(EColorBits); //定义好后引用 /*~ This property lists flags matching the names of values from EColorBits. */ UPROPERTY(EditAnywhere, Meta (Bitmask, BitmaskEnum EColorBits)) int32 ColorFlags; /*~ MyOtherFunction shows flags named after the values from EColorBits. */ UFUNCTION(BlueprintCallable) void MyOtherFunction(UPARAM(meta (Bitmask, BitmaskEnum EColorBits)) int32 ColorFlagsParam)// Floating Point Types floatdouble// Boolean Types 可使用C bool关键字或位域 uint32 bIsHungry : 1; bool bIsThirsty;// Strings 支持三种核心类型的字符串 // FString 是典型的动态字符数组字符串类型 // FName 是对全局字符串表中不可变且不区分大小写的字符串的引用相较于FString大小更小更能高效的传递但更难以操控 // FText 是指定用于处理本地化的更可靠的字符串表示 // 大多数情况下使用TCHAR类型来表示字符TEXT()宏可用于表示TCHAR文字 MyDogPtr-DogName FName(TEXT(Samson Aloysius));Property SpecifiersAdvancedDisplay属性将被放置在高级选项下AssetRegistrySearchable此属性及其值都将自动添加到资产注册表中BlueprintAssignable仅适用于多播代理公开要在蓝图中分配的属性BlueprintAuthorityOnly必须是多播代理在蓝图中只接受标记为BlueprintAuthorityOnly的事件BlueprintCallable仅限多播代理应公开属性以在Blueprint代码中调用BlueprintGetterGetterFunctionName指定自定义访问器函数如也没有标记BlueprintSetter或BlueprintReadWrite则隐式地为BlueprintReadOnlyBlueprintSetterSetterFunctionName具有自定义赋值函数并隐式标记为BlueprintReadWrite注意mutator函数必须命名并属于同一类BlueprintReadOnly蓝图只读此属性与BlueprintReadWrite规范不兼容BlueprintReadWrite蓝图可读写此属性与BlueprintReadOnly规范不兼容CategoryTopCategory\|SubCategory\|...指定在蓝图中显示属性类别使用|运算符定义嵌套类别DuplicateTransient在任何类型的复制复制/粘贴、二进制复制等过程中属性的值都应重置为类默认值EditAnywhere可通过原型和实例上的属性窗口进行编辑与Visible说明符不兼容VisibleAnywhere在所有属性窗口中可见但无法编辑与“Edit”规范不兼容EditDefaultsOnly只可通过原型的属性窗口进行编辑与Visible说明符不兼容EditInstanceOnly只可通过实例上的属性窗口进行编辑与Visible说明符不兼容EditFixedSize仅适用于动态数组将防止用户通过虚幻编辑器属性窗口更改数组的长度EditInline允许在属性检查器中编辑此属性引用的对象的属性仅适用于对象引用包括对象引用数组Export仅适用于对象属性或对象数组。指示在复制对象时例如用于复制/粘贴操作分配给此属性的对象应作为子对象块整体导出而不是仅输出对象引用本身Config属性将可配置当前值可以保存到与类关联的.ini文件中并在创建时加载在默认属性中不能给值隐式BlueprintReadOnlyGlobalConfig与Config相似只是不能在子类中重写它在默认属性中不能给值隐式BlueprintReadOnlyInstanced仅限于对象UCLASS属性当创建此类的实例时将获得默认情况下分配给此属性的Object的唯一副本用于实例化类默认属性中定义的子对象隐式EditInline、ExportInterp该值可由序列器中的轨迹随时间驱动Localized定义一个本地化值主要用于字符串隐式ReadOnlyNativeC代码负责对其进行序列化并暴露给垃圾回收NoClear防止编辑器将此对象引用设置为无隐藏编辑器中的清除和浏览按钮NoExport仅对native类有用不应包含在自动生成的类声明中NonPIEDuplicateTransient在复制过程中将重置为默认值除非是PIENonTransactional对此属性值的更改不会包含在编辑器的撤消/重做历史记录中NotReplicated跳过复制仅适用于服务请求函数中的结构体成员和参数Replicated该属性应通过网络进行复制ReplicatedUsingFunctionName指定了一个回调函数当属性通过网络更新时执行该函数RepRetry仅对结构体属性有用如此属性未能完全发送如对象引用尚无法通过网络序列化请重试复制对于简单的引用这是默认值但对于结构体由于带宽成本这通常是不可取的因此除非指定此标志否则它将被禁用SaveGame一种在属性级别显式包含检查点/保存系统字段的简单方法该标志应设置在所有旨在成为已保存游戏一部分的字段上然后可以使用代理存档器对其进行读/写SerializeTextnative属性应序列化为文本ImportText、ExportTextSkipSerialization此属性不会被序列化但仍然可以导出为文本格式如用于复制/粘贴操作SimpleDisplay可见或可编辑的属性显示在“Details”面板中无需打开“Advanced”部分即可查看TextExportTransient此属性不会导出为文本格式因此不能用于复制/粘贴操作Transient属性是瞬态的意味着不会被保存或加载以这种方式标记的属性将在加载时填充为零VisibleDefaultsOnly此属性仅在原型的属性窗口中可见不能编辑与任何“Edit”都不兼容VisibleInstanceOnly此属性仅在实例的属性窗口中可见对原型不可见且不可编辑与任何“Edit”都不兼容Metadata Specifiers声明类、接口、结构体、枚举、枚举值、函数或属性时可添加元数据说明符来控制其与引擎和编辑器各方面的相处方式每一种类型的数据结构或成员都有自己的元数据说明符列表注Metadata只存在于编辑器中不要编写能够访问到Metadata的游戏逻辑AllowAbstracttrue/false用于Subclass和SoftClass属性说明抽象类属性是否应显示在类选取器中AllowedClassesClass1, Class2, ..用于FSoftObjectPath属性逗号分隔的列表表明要显示在资源选取器中的资源类类型AllowPreserveRatio用于Fvector属性在细节面板中显示此属性时将添加一个比率锁ArrayClampArrayProperty用于整数属性将可在UI中输入的有效值锁定在0和命名数组属性的长度之间AssetBundles用于SoftObjectPtr或SoftObjectPath属性主数据资源中使用的束列表命名指定此引用属于哪个束的一部分BlueprintBaseOnly用于Subclass和SoftClass属性说明蓝图类是否应显示在类选取器中BlueprintCompilerGeneratedDefaults属性默认项由蓝图编译器生成CopyPropertiesForUnrelatedObjects在编译后调用时将不会被复制ClampMinN用于浮点和整数属性指定可在属性中输入的最小值NClampMaxN用于浮点和整数属性。指定可在属性中输入的最大值NConfigHierarchyEditable此属性被序列化为一个配置.ini文件可在配置层级中的任意处进行设置ContentDir由FDirectoryPath属性使用说明将使用Content文件夹中的Slate风格目录选取器来选取路径DisplayAfterPropertyName在蓝图编辑器中名为PropertyName的属性后即刻显示此属性前提是两个属性属于同一类别则忽略其在源代码中的顺序进行显示如多个属性有相同的DisplayAfter值和相同的DisplayPriority值将在指定属性之后按照自身在标头文件中声明的顺序显示DisplayNameProperty Name此属性显示的命名不显示代码生成的命名DisplayPriorityN如两个属性有相同的DisplayAfter值或属于同一类别且无DisplayAfter元标签则此属性将决定其顺序最高优先级值为1表示DisplayPriority值为1的属性将在DisplayProirity值为2的属性之上显示如多个属性有相同的DisplayAfter值其将按照在标头文件中声明的顺序显示DisplayThumbnailtrue说明属性是一个资源类型其应显示选中资源的缩略图EditConditionBooleanPropertyName对一个布尔属性进行命名此属性用于说明此属性的编辑是否被禁用将!放置在属性命名前可颠倒测试EditFixedOrder使排列的元素无法通过拖拽来重新排序ExactClasstrue结合AllowedClasses用于FSoftObjectPath属性说明是否只能使用AllowedClasses中指定的准确类或子类是否同样有效ExposeFunctionCategoriesCategory1, Category2, ..在蓝图编辑器中编译一个函数列表时指定其函数应被公开的类目的列表ExposeOnSpawntrue指定此属性是否应在此类类型的一个Spawn Actor节点上公开FilePathFilterFileType由FFilePath属性使用说明在文件选取器中显示的路径过滤器常规值包括uasset和umap但这些并非唯一可能的值GetByRef使该属性的Get蓝图节点返回对属性的常量引用而不是其值的副本只对稀疏类数据生效只能在不存在NoGetter时使用HideAlphaChannel用于Fcolor和FLinearColor属性说明详细显示属性控件时Alpha属性应为隐藏状态HideViewOptions用于Subclass和SoftClass属性隐藏在类选取器中修改显示选项的功能InlineEditConditionToggle表示出布尔属性只内联显示为其他属性中的一个编辑条件切换不应显示在其自身的行上LongPackageName由FDirectoryPath属性使用将路径转换为一个长的包命名MakeEditWidget用于变换或旋转体属性或变换/旋转体的排列说明属性应在视口中公开为一个可移动控件NoGetter防止蓝图为该属性生成一个get节点只对稀疏类数据生效ScriptNameDisplayName在将此类、属性或函数导出到脚本语言时使用的名称可以包含以启用的名称作为以分号分隔的额外条目二UFunctionsUFunction是UE反射系统可识别的C函数UObject或蓝图函数库都可将成员函数声明为UFunction通过在头文件中将UFunction宏放置在函数声明上方宏将支持函数说明符来更改虚幻引擎解译和使用函数的方式UFUNCTION([specifier1setting1, specifier2, ...], [meta(key1value1, key2, ...)]) ReturnType FunctionName([Parameter1, Parameter2, ..., ParameterN1DefaultValueN1, ParameterN2DefaultValueN2]) [const];通过函数说明符将UFunctions公共给蓝图可视化脚本Blueprint Visual Scripting图表以便开发者从蓝图调用或扩展UFunction而无需更改C代码在类的默认属性中UFunctions可绑定到Delegates以执行一些操作如将操作与用户输入相关联还可充当网络回调意味着当某个变量受网络更新影响时用户可以将其用于接收通知并运行自定义代码用户甚至可创建自己的控制台命令通常为debug、configuration或cheat code命令并能在开发版本中从游戏控制台调用这些命令或将拥有自定义功能的按钮添加到关卡编辑器中的游戏对象Function Specifiers声明函数时可添加函数说明符以控制函数相对于引擎和编辑器的各个方面的行为方式BlueprintAuthorityOnly如在具有网络权限的机器上运行服务器、专用服务器或单人游戏此函数将仅从蓝图代码执行BlueprintCallable函数可在蓝图或关卡蓝图图表内执行BlueprintCosmetic此函数为修饰性的无法在专用服务器上运行BlueprintImplementableEvent此函数可在蓝图或关卡蓝图图表内实现BlueprintPure此函数不对拥有它的对象产生任何影响可在蓝图或关卡蓝图图表中执行默认带有const标记的函数将作为纯函数公开使用BlueprintPurefalse可设置为非纯函数纯函数不会缓存结果因此在对蓝图函数进行任何重大操作时都需要小心比较好的做法是避免在蓝图纯函数中输出数组属性CallInEditor可在实例上通过细节面板中调用此函数Category TopCategory\|SubCategory\|Etc在蓝图编辑工具中显示指定函数的类别使用 | 运算符定义嵌套类别BlueprintNativeEvent此函数旨在被蓝图覆盖掉但也具有默认原生实现用于声明名称与主函数相同的附加函数但末尾添加了_Implementation是写入代码的位置如未找到任何蓝图覆盖该自动生成的代码将调用_Implementation方法Client此函数仅在调用此函数对象的客户端上执行用于声明名称与主函数相同的附加函数但末尾添加了_Implementation必要时此自动生成的代码将调用_Implementation方法Server此函数仅在服务器上执行用于声明名称与主函数相同的附加函数但末尾添加了_Implementation是写入代码的位置必要时此自动生成的代码将调用_Implementation方法WithValidation用于声明名称与主函数相同的附加函数但末尾需要添加_Validate此函数使用相同的参数但是会返回bool以指示是否应继续调用主函数CustomThunkUnrealHeaderTool代码生成器将不为此函数生成thunk用户需要自己通过DECLARE_FUNCTION或DEFINE_FUNCTION宏来提供thunkExec此函数可从游戏内控制台执行仅在特定类中声明时Exec命令才有效NetMulticast此函数将在服务器上本地执行也将复制到所有客户端上无论该Actor的NetOwner为何Reliable此函数将通过网络复制并且一定会到达即使出现带宽或网络错误仅在与Client或Server配合使用时才有效Unreliable此函数将通过网络复制但可能会因带宽限制或网络错误而失败仅在与Client或Server配合使用时才有效SealedEvent无法在子类中覆盖此函数SealedEvent关键词只能用于事件对于非事件函数请声明为static或final以密封它们ServiceRequest此函数为RPC远程过程调用服务请求这意味着NetMulticast和ReliableServiceResponse此函数为RPC服务响应这意味着NetMulticast和ReliableMetadata Specifiers声明类、接口、结构体、枚举、枚举值、函数或属性时可添加元数据说明符来控制其与引擎和编辑器各方面的相处方式每一种类型的数据结构或成员都有自己的元数据说明符列表注Metadata只存在于编辑器中不要编写能够访问到Metadata的游戏逻辑AdvancedDisplayParameter1, Parameter2, ..以逗号分隔的参数列表将显示为高级引脚需UI扩展AdvancedDisplayN用一个数字替代N第N之后的所有参数将显示为高级引脚需UI扩展如AdvancedDisplay2 将把前两个之外的所有参数标记为高级ArrayParmParameter1, Parameter2, ..说明BlueprintCallable函数应使用一个Call Array Function节点且列出的参数应被视为通配符数组属性ArrayTypeDependentParamsParameter使用ArrayParm时此说明符将指定一个参数其将确定ArrayParm列表中所有参数的类型AutoCreateRefTermParameter1, Parameter2, ..如列出参数由引用传递的引脚未连接其将拥有一个自动创建的默认项这是蓝图的一个便利功能经常在数组引脚上使用BlueprintAutocast仅能由来自蓝图函数库的静态BlueprintPure函数使用Cast节点将根据返回类型和函数首个参数的类型来自动添加BlueprintInternalUseOnly此函数是一个内部实现细节用于实现另一个函数或节点其不会直接在蓝图图表中公开BlueprintProtected此函数只能在蓝图中的拥有对象上调用其无法在另一个实例上调用CallableWithoutWorldContext用于拥有一个WorldContext引脚的BlueprintCallable函数说明函数可被调用即使其类不实现GetWorld函数也同样如此CommutativeAssociativeBinaryOperator说明BlueprintCallable函数应使用Commutative Associative Binary节点此节点缺少引脚命名但拥有一个创建额外输入引脚的添加引脚Add Pin按钮CompactNodeTitleName说明BlueprintCallable函数应在压缩显示模式中显示并提供在该模式中显示的命名CustomStructureParamParameter1, Parameter2, ..列出的参数都会被视为通配符DefaultToSelf用于BlueprintCallable函数说明对象属性的命名默认值应为节点的自我情境HideSelfPin隐藏用于指出函数调用所处对象的self引脚self引脚在与调用蓝图的类兼容的BlueprintPure函数上为自动隐藏状态这通常与DefaultToSelf说明符共用DeprecatedFunction蓝图对此函数进行引用时将引起编译警告告知用户函数已废弃可使用DeprecationMessage元数据说明符添加到废弃警告消息如提供说明如何替代已废弃的函数DeprecationMessageMessage Text如果函数已废弃尝试编译使用此函数的蓝图时其将被添加到标准废弃警告DeterminesOutputTypeParameter函数的返回类型将根据连接到命名参数引脚的输入动态更改该参数应该是一个模板类型比如TSubClassOfX或TSoftObjectPtrX其中函数的原始返回类型是X*或带有X*作为值类型的容器比如TArrayX*DevelopmentOnly被标记为DevelopmentOnly的函数只会在Development模式中运行。这适用于调试输出之类的功能但其不应存在于发布产品中DisplayNameBlueprint Node Name此节点在蓝图中的命名将被此处提供的值所取代而非代码生成的命名ExpandEnumAsExecsParameter用于BlueprintCallable函数说明应为参数使用的枚举中的每个条目创建一个输入执行引脚命名参数必须是引擎通过UENUM标签识别的一个列举类型ForceAsFunction将没有来自事件的返回值的BlueprintImplementableEvent更改为函数HidePinParameter用于BlueprintCallable函数说明参数引脚应从用户视图中隐藏注使用此方式每个函数只能隐藏一个参数引脚InternalUseParamParameter与HidePin相似这将在用户视图中隐藏命名参数的引脚只能用于一个函数的一个参数KeyWordsSet Of Keywords指定在搜索此函数时可使用的一套关键词如合适放置节点在蓝图图表中调用函数Latent说明一个延迟操作延迟操作拥有类型为FLatentActionInfo的一个参数此参数由LatentInfo说明符命名LatentInfoParameter用于延迟BlueprintCallable函数说明哪个参数是LatentInfo参数MaterialParameterCollectionFunction用于BlueprintCallable函数说明应使用材质覆盖节点NativeBreakFunc用于BlueprintCallable函数说明函数应以标准Break Struct节点的方式进行显示NotBlueprintThreadSafe只在蓝图函数库中有效此函数将被视为拥有类的整体BlueprintThreadSafe元数据的一个例外ShortToolTipShort tooltip完整提示文本过长时使用的简短提示文本如父类选取器对话ToolTipHand-written tooltip覆盖从代码注释自动生成的提示文本UnsafeDuringActorConstruction在Actor构造时调用此函数并非安全操作WorldContextParameter由BlueprintCallable函数使用说明哪个参数决定运算正在发生的WorldScriptNameDisplayName在将此类、属性或函数导出到脚本语言时使用的名称可以包含以启用的名称作为以分号分隔的额外条目Function Parameter SpecifiersOut声明由引用传递的参数使函数对其进行修改Optional通过任选关键词可使部分函数参数变为任选便于调用任选参数的数值调用方未指定取决于函数Delegates委托可以以泛型、类型安全的方式调用C对象上的成员函数委托可以动态绑定到任意对象的成员函数在将来调用该对象的函数即使调用者不知道该对象的类型Timers定时器可用于在一段延迟后执行某个动作或在一段时间内执行动作如可以让玩家在获得某个物品后保持无敌10秒并在10秒后失去无敌效果或让玩家在进入毒气场景后每秒受到伤害这类效果都可以通过定时器实现三Metadata Specifiers声明UClasses、UFunctions、UProperties、UEnums和UInterfaces时使用的元数据关键词表示其与引擎和关卡编辑器诸多方面的互动方式当声明classe、interfaces、structs、enums、enum values、functions、or propertie时可添加Metadata Specifiers以控制其与引擎和编辑器各方面的交互方式每一种类型的数据结构或成员都有自己的元数据说明符列表注Metadata仅存在于编辑器中不要编写能够访问到Metadata的游戏逻辑使用单词meta后接说明符列表来添加元数据说明符可以将它们的值添加到UCLASS、UENUM、UINTERFACE、USTRUCT、UFUNCTION或UPROPERTY宏{UCLASS/UENUM/UINTERFACE/USTRUCT/UFUNCTION/UPROPERTY}(SpecifierX, meta(MetaTag1Value1, MetaTag2, ..), SpecifierY)添加Metadata Specifiers到枚举类型内的特定值可将UMETA标签添加到值本身UENUM() enum class EMyEnum : uint8 { // DefaultValue Tooltip DefaultValue 0 UMETA(MetaTag1Value1, MetaTag2, ..), // ValueWithoutMetaSpecifiers Tooltip ValueWithoutMetaSpecifiers, // ValueWithMetaSpecifiers Tooltip ValueWithMetaSpecifiers UMETA((MetaTag1Value1, MetaTag2, ..), // FinalValue Tooltip FinalValue (MetaTag1Value1, MetaTag2, ..) };四Unreal Smart Pointer Library虚幻智能指针库为C11智能指针的自定义实现旨在减轻内存分配和追踪的负担该实现包括行业标准共享指针Shared Pointers、弱指针Weak Pointers和唯一指针Unique Pointers其还可添加共享引用Shared References此类引用的行为与不可为空的共享指针相同虚幻Objects使用更适合游戏代码的单独内存追踪系统因此这些类无法与UObject系统同时使用Smart Pointer Types智能指针可影响其包含或引用对象的寿命不同智能指针对对象有不同的限制和影响Shared Pointers(TSharedPtr)共享指针拥有其引用的对象无限防止该对象被删除并在无共享指针或共享引用见下文引用其时最终处理其的删除共享指针可为空意味其不引用任何对象任何非空共享指针都可对其引用的对象生成共享引用Shared References(TSharedRef)共享引用的行为与共享指针类似即其拥有引用的对象对于空对象而言其存在不同共享引用须总是引用非空对象共享指针无此类限制因此共享引用可转换为共享指针且该共享指针引用有效对象要确认引用的对象是非空或者要表明共享对象所有权时请使用共享引用Weak Pointers(TWeakPtr)弱指针类与共享指针类似但不拥有其引用的对象因此不影响其生命周期此属性中断引用循环因此十分有用但也意味弱指针可在无预警的情况下随时变为空因此弱指针可生成指向其引用对象的共享指针确保程序员能对该对象进行安全临时访问Unique Pointers(TUniquePtr)唯一指针仅会显式拥有其引用的对象仅有一个唯一指针指向给定资源因此唯一指针可转移所有权但无法共享复制唯一指针的任何尝试都将导致编译错误唯一指针超出范围时其将自动删除其所引用的对象注对唯一指针引用的对象进行共享指针或共享引用的操作十分危险即使其他智能指针继续引用该对象此操作不会取消唯一指针自身被销毁时删除该对象的行为同样不应为共享指针或共享引用引用的对象创建唯一指针Benefits of Smart Pointers防止内存泄漏共享引用不存在时智能指针弱指针除外会自动删除对象弱引用弱指针会中断引用循环并阻止悬挂指针可选择的线程安全能指针库包括线程安全代码可跨线程管理引用计数如无需线程安全可用其换取更好性能运行时安全共享引用从不为空可随时取消引用;传达意图可轻松区分对象所有者和观察者内存智能指针在64位下仅为C指针大小的两倍加上共享的16字节引用控制器唯一指针除外其与C指针大小相同Helper Classes and Functions虚幻智能指针库提供多个助手类和函数以便使用智能指针时更加容易、直观ClassesTSharedFromThis从TSharedFromThis派生类添加AsSharedorSharedThis函数此类函数可获取对象的TSharedRefFunctionsMakeShared、MakeShareable在常规C指针中创建共享指针MakeShared会在单个内存块中分配新的对象实例和引用控制器但要求对象提交public构造函数MakeShareable的效率较低但即使对象的构造函数为私有其仍可运行利用此操作可拥有非自己创建的对象并在删除对象时支持自定义行为StaticCastSharedRef、StaticCastSharedPtr静态投射效用函数通常用于向下投射到派生类型ConstCastSharedRef、ConstCastSharedPtr将const智能引用或智能指针分别转换为mutable智能引用或智能指针智能指针实现细节在功能和效率方面虚幻智能指针库中的智能指针具有一些共同特征Speed要使用智能指针时始终考虑性能智能指针非常适合某些高级系统、资源管理或工具编程但部分智能指针类型比原始C指针更慢这种开销使得其在低级引擎代码如渲染中用处不大智能指针的部分性能优势包括所有运算均为常量时间取消引用多数智能指针的速度和原始C指针的相同在发布版本中复制智能指针不会分配内存线程安全智能指针是无锁的智能指针的性能缺陷包括创建和复制智能指针比创建和复制原始C指针需要更多开销保持引用计数增加基本运算的周期部分智能指针占用的内存比原始的C更多引用控制器有两个堆分配使用MakeShared代替MakeShareable可避免二次分配并可提高性能Intrusive Accessors共享指针是non-intrusive意味对象不知道其是否为智能指针拥有此通常是可以接受的但在某些情况下可能要将对象作为共享引用或共享指针进行访问为此使用对象的类作为模板参数从TSharedFromThis派生对象的类TSharedFromThis提供两个函数AsShared和SharedThis可将对象转换为共享引用并从共享引用转换为共享指针使用固定返回共享引用的类factory时或需将对象传到需要共享引用或共享指针的系统时此操作十分有用AsShared会将类返回为最初作为模板参数传到TSharedFromThis的类型返回其可能是调用对象的父类型而SharedThis将直接从该类型衍生类型并返回引用该类型对象的智能指针class FRegistryObject; class FMyBaseClass: public TSharedFromThisFMyBaseClass { virtual void RegisterAsBaseClass(FRegistryObject* RegistryObject) { // Access a shared reference to this. // We are directly inherited from TSharedFromThis , so AsShared() and SharedThis(this) return the same type. TSharedRefFMyBaseClass ThisAsSharedRef AsShared(); // RegistryObject expects a TSharedRefFMyBaseClass, or a TSharedPtrFMyBaseClass. TSharedRef can implicitly be converted to a TSharedPtr. RegistryObject-Register(ThisAsSharedRef); } }; class FMyDerivedClass : public FMyBaseClass { virtual void Register(FRegistryObject* RegistryObject) override { // We are not directly inherited from TSharedFromThis, so AsShared() and SharedThis(this) return different types. // AsShared() will return the type originally specified in TSharedFromThis - TSharedRefFMyBaseClass in this example. // SharedThis(this) will return a TSharedRef with the type of this - TSharedRefFMyDerivedClass in this example. // The SharedThis() function is only available in the same scope as the this pointer. TSharedRefFMyDerivedClass AsSharedRef SharedThis(this); // RegistryObject will accept a TSharedRefFMyDerivedClass because FMyDerivedClass is a type of FMyBaseClass. RegistryObject-Register(ThisAsSharedRef); } }; class FRegistryObject { // This function will accept a TSharedRef or TSharedPtr to FMyBaseClass or any of its children. void Register(TSharedRefFMyBaseClass); };不要在构造函数中调用AsShared或Shared共享引用此时并未初始化将导致崩溃或断言Casting可通过虚幻智能指针库包含的多个支持函数cast共享指针(和共享引用)Up-casting是隐式的与C指针相同可使用ConstCastSharedPtr函数进行const cast使用StaticCastSharedPtr进行static cast通常是downcast到派生类指针无run-type类型的信息RTTI因此不支持动态转换// This assumes we validated that the FDragDropOperation is actually an FAssetDragDropOp through other means. TSharedPtrFDragDropOperation Operation DragDropEvent.GetOperation(); // We can now cast with StaticCastSharedPtr. TSharedPtrFAssetDragDropOp DragDropOp StaticCastSharedPtrFAssetDragDropOp(Operation);Thread Safety通常仅在单线程上访问智能指针的操作才是安全的。如需访问多线程请使用智能指针类的线程安全版本TSharedPtrT, ESPMode::ThreadSafeTSharedRefT, ESPMode::ThreadSafeTWeakPtrT, ESPMode::ThreadSafeTSharedFromThisT, ESPMode::ThreadSafe由于原子引用计数此类线程安全版本比默认版本稍慢但其行为与常规C指针一致读取和复制固定为线程安全写入和重置须同步后才安全注如多线程永不访问指针可通过避免使用线程安全版本获得更好性能提示和限制避免将数据作为TSharedRef或TSharedPtr参数传到函数此操作将因取消引用和引用计数而产生开销相反建议将引用对象作为const 进行传递可将共享指针向前声明为不完整类型共享指针与虚幻对象(UObject及其派生类)不兼容引擎具有UObject管理的单独内存管理系统两个系统未互相重叠