目录
四,Unreal Smart Pointer Library
一,Properties
Properties 属性使用标准的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
float,double
// Boolean Types 可使用C++ bool关键字或位域
uint32 bIsHungry : 1;
bool bIsThirsty;
// Strings 支持三种核心类型的字符串
// FString 是典型的"动态字符数组"字符串类型;
// FName 是对全局字符串表中不可变且不区分大小写的字符串的引用;相较于FString,大小更小,更能高效的传递,但更难以操控;
// FText 是指定用于处理本地化的更可靠的字符串表示;
// 大多数情况下,使用TCHAR类型来表示字符,TEXT()宏可用于表示TCHAR文字;
MyDogPtr->DogName = FName(TEXT("Samson Aloysius"));
Property Specifiers
| AdvancedDisplay | 属性将被放置在高级选项下; |
| AssetRegistrySearchable | 此属性及其值都将自动添加到资产注册表中; |
| BlueprintAssignable | 仅适用于多播代理,公开要在蓝图中分配的属性; |
| BlueprintAuthorityOnly | 必须是多播代理,在蓝图中,只接受标记为BlueprintAuthorityOnly的事件; |
| BlueprintCallable | 仅限多播代理,应公开属性以在Blueprint代码中调用; |
| BlueprintGetter=GetterFunctionName | 指定自定义访问器函数,如也没有标记BlueprintSetter或BlueprintReadWrite,则隐式地为BlueprintReadOnly; |
| BlueprintSetter=SetterFunctionName | 具有自定义赋值函数,并隐式标记为BlueprintReadWrite;注意,mutator函数必须命名并属于同一类; |
| BlueprintReadOnly | 蓝图只读此属性,与BlueprintReadWrite规范不兼容; |
| BlueprintReadWrite | 蓝图可读写此属性,与BlueprintReadOnly规范不兼容; |
| Category="TopCategory\|SubCategory\|..." | 指定在蓝图中显示属性类别,使用|运算符定义嵌套类别; |
| DuplicateTransient | 在任何类型的复制(复制/粘贴、二进制复制等)过程中,属性的值都应重置为类默认值; |
| EditAnywhere | 可通过原型和实例上的属性窗口进行编辑,与"Visible"说明符不兼容; |
| VisibleAnywhere | 在所有属性窗口中可见,但无法编辑;与“Edit”规范不兼容; |
| EditDefaultsOnly | 只可通过原型的属性窗口进行编辑,与"Visible"说明符不兼容; |
| EditInstanceOnly | 只可通过实例上的属性窗口进行编辑,与"Visible"说明符不兼容; |
| EditFixedSize | 仅适用于动态数组,将防止用户通过虚幻编辑器属性窗口更改数组的长度; |
| EditInline | 允许在属性检查器中编辑此属性引用的对象的属性(仅适用于对象引用,包括对象引用数组); |
| Export | 仅适用于对象属性(或对象数组)。指示在复制对象时(例如用于复制/粘贴操作),分配给此属性的对象应作为子对象块整体导出,而不是仅输出对象引用本身; |
| Config | 属性将可配置;当前值可以保存到与类关联的.ini文件中,并在创建时加载;在默认属性中不能给值;隐式BlueprintReadOnly; |
| GlobalConfig | 与Config相似,只是不能在子类中重写它;在默认属性中不能给值;隐式BlueprintReadOnly; |
| Instanced | 仅限于对象(UCLASS)属性;当创建此类的实例时,将获得默认情况下分配给此属性的Object的唯一副本;用于实例化类默认属性中定义的子对象;隐式EditInline、Export; |
| Interp | 该值可由序列器中的轨迹随时间驱动; |
| Localized | 定义一个本地化值,主要用于字符串,隐式ReadOnly; |
| Native | C++代码负责对其进行序列化并暴露给垃圾回收; |
| NoClear | 防止编辑器将此对象引用设置为无,隐藏编辑器中的清除(和浏览)按钮; |
| NoExport | 仅对native类有用,不应包含在自动生成的类声明中; |
| NonPIEDuplicateTransient | 在复制过程中,将重置为默认值,除非是PIE; |
| NonTransactional | 对此属性值的更改不会包含在编辑器的撤消/重做历史记录中; |
| NotReplicated | 跳过复制,仅适用于服务请求函数中的结构体成员和参数; |
| Replicated | 该属性应通过网络进行复制; |
| ReplicatedUsing=FunctionName | 指定了一个回调函数,当属性通过网络更新时执行该函数; |
| RepRetry | 仅对结构体属性有用;如此属性未能完全发送(如,对象引用尚无法通过网络序列化),请重试复制;对于简单的引用,这是默认值,但对于结构体,由于带宽成本,这通常是不可取的,因此除非指定此标志,否则它将被禁用; |
| SaveGame | 一种在属性级别显式包含检查点/保存系统字段的简单方法;该标志应设置在所有旨在成为已保存游戏一部分的字段上,然后可以使用代理存档器对其进行读/写; |
| SerializeText | native属性应序列化为文本(ImportText、ExportText); |
| SkipSerialization | 此属性不会被序列化,但仍然可以导出为文本格式(如用于复制/粘贴操作); |
| SimpleDisplay | 可见或可编辑的属性显示在“Details”面板中,无需打开“Advanced”部分即可查看; |
| TextExportTransient | 此属性不会导出为文本格式(因此不能用于复制/粘贴操作); |
| Transient | 属性是瞬态的,意味着不会被保存或加载;以这种方式标记的属性将在加载时填充为零; |
| VisibleDefaultsOnly | 此属性仅在原型的属性窗口中可见,不能编辑;与任何“Edit”都不兼容; |
| VisibleInstanceOnly | 此属性仅在实例的属性窗口中可见,对原型不可见,且不可编辑;与任何“Edit”都不兼容; |
Metadata Specifiers
声明类、接口、结构体、枚举、枚举值、函数,或属性时,可添加 元数据说明符 来控制其与引擎和编辑器各方面的相处方式;每一种类型的数据结构或成员都有自己的元数据说明符列表;
注,Metadata只存在于编辑器中,不要编写能够访问到Metadata的游戏逻辑;
| AllowAbstract="true/false" | 用于Subclass和SoftClass属性,说明抽象类属性是否应显示在类选取器中; |
| AllowedClasses="Class1, Class2, .." | 用于FSoftObjectPath属性,逗号分隔的列表,表明要显示在资源选取器中的资源类类型; |
| AllowPreserveRatio | 用于Fvector属性;在细节面板中显示此属性时将添加一个比率锁; |
| ArrayClamp="ArrayProperty" | 用于整数属性,将可在UI中输入的有效值锁定在0和命名数组属性的长度之间; |
| AssetBundles | 用于SoftObjectPtr或SoftObjectPath属性,主数据资源中使用的束列表命名,指定此引用属于哪个束的一部分; |
| BlueprintBaseOnly | 用于Subclass和SoftClass属性,说明蓝图类是否应显示在类选取器中; |
| BlueprintCompilerGeneratedDefaults | 属性默认项由蓝图编译器生成,CopyPropertiesForUnrelatedObjects在编译后调用时将不会被复制; |
| ClampMin="N" | 用于浮点和整数属性,指定可在属性中输入的最小值N; |
| ClampMax="N" | 用于浮点和整数属性。指定可在属性中输入的最大值N; |
| ConfigHierarchyEditable | 此属性被序列化为一个配置(.ini)文件,可在配置层级中的任意处进行设置; |
| ContentDir | 由FDirectoryPath属性使用,说明将使用Content文件夹中的Slate风格目录选取器来选取路径; |
| DisplayAfter="PropertyName" | 在蓝图编辑器中,名为PropertyName的属性后即刻显示此属性;前提是两个属性属于同一类别,则忽略其在源代码中的顺序进行显示;如多个属性有相同的DisplayAfter值和相同的DisplayPriority值,将在指定属性之后,按照自身在标头文件中声明的顺序显示; |
| DisplayName="Property Name" | 此属性显示的命名,不显示代码生成的命名; |
| DisplayPriority="N" | 如两个属性有相同的DisplayAfter值,或属于同一类别且无DisplayAfter元标签,则此属性将决定其顺序;最高优先级值为1,表示DisplayPriority值为1的属性将在DisplayProirity值为2的属性之上显示;如多个属性有相同的DisplayAfter值,其将按照在标头文件中声明的顺序显示; |
| DisplayThumbnail="true" | 说明属性是一个资源类型,其应显示选中资源的缩略图; |
| EditCondition="BooleanPropertyName" | 对一个布尔属性进行命名,此属性用于说明此属性的编辑是否被禁用;将"!"放置在属性命名前可颠倒测试; |
| EditFixedOrder | 使排列的元素无法通过拖拽来重新排序; |
| ExactClass="true" | 结合AllowedClasses用于FSoftObjectPath属性;说明是否只能使用AllowedClasses中指定的准确类,或子类是否同样有效; |
| ExposeFunctionCategories="Category1, Category2, .." | 在蓝图编辑器中编译一个函数列表时,指定其函数应被公开的类目的列表; |
| ExposeOnSpawn="true" | 指定此属性是否应在此类类型的一个Spawn Actor节点上公开; |
| FilePathFilter="FileType" | 由FFilePath属性使用;说明在文件选取器中显示的路径过滤器;常规值包括"uasset"和"umap",但这些并非唯一可能的值; |
| GetByRef | 使该属性的"Get"蓝图节点返回对属性的常量引用,而不是其值的副本;只对稀疏类数据生效,只能在不存在NoGetter时使用; |
| HideAlphaChannel | 用于Fcolor和FLinearColor属性;说明详细显示属性控件时Alpha属性应为隐藏状态; |
| HideViewOptions | 用于Subclass和SoftClass属性;隐藏在类选取器中修改显示选项的功能; |
| InlineEditConditionToggle | 表示出布尔属性只内联显示为其他属性中的一个编辑条件切换,不应显示在其自身的行上; |
| LongPackageName | 由FDirectoryPath属性使用;将路径转换为一个长的包命名; |
| MakeEditWidget | 用于变换或旋转体属性,或变换/旋转体的排列;说明属性应在视口中公开为一个可移动控件; |
| NoGetter | 防止蓝图为该属性生成一个"get"节点,只对稀疏类数据生效; |
| ScriptName="DisplayName" | 在将此类、属性或函数导出到脚本语言时使用的名称;可以包含以启用的名称作为以分号分隔的额外条目; |
二,UFunctions
UFunction是UE反射系统可识别的C++函数,UObject或蓝图函数库都可将成员函数声明为UFunction,通过在头文件中将 UFunction 宏放置在函数声明上方;宏将支持 函数说明符 来更改虚幻引擎解译和使用函数的方式;
UFUNCTION([specifier1=setting1, specifier2, ...], [meta(key1="value1", key2, ...)])
ReturnType FunctionName([Parameter1, Parameter2, ..., ParameterN1=DefaultValueN1, ParameterN2=DefaultValueN2]) [const];
通过函数说明符将UFunctions公共给蓝图可视化脚本(Blueprint Visual Scripting)图表,以便开发者从蓝图调用或扩展UFunction,而无需更改C++代码;
在类的默认属性中,UFunctions可绑定到Delegates,以执行一些操作(如将操作与用户输入相关联);还可充当网络回调,意味着当某个变量受网络更新影响时,用户可以将其用于接收通知并运行自定义代码;
用户甚至可创建自己的控制台命令(通常为 debug、configuration 或 cheat code 命令),并能在开发版本中从游戏控制台调用这些命令,或将拥有自定义功能的按钮添加到关卡编辑器中的游戏对象;
Function Specifiers
声明函数时,可添加 函数说明符,以控制函数相对于引擎和编辑器的各个方面的行为方式;
| BlueprintAuthorityOnly | 如在具有网络权限的机器上运行(服务器、专用服务器或单人游戏),此函数将仅从蓝图代码执行; |
| BlueprintCallable | 函数可在蓝图或关卡蓝图图表内执行; |
| BlueprintCosmetic | 此函数为修饰性的,无法在专用服务器上运行; |
| BlueprintImplementableEvent | 此函数可在蓝图或关卡蓝图图表内实现; |
| BlueprintPure | 此函数不对拥有它的对象产生任何影响,可在蓝图或关卡蓝图图表中执行; 默认,带有 纯函数不会缓存结果,因此在对蓝图函数进行任何重大操作时都需要小心;比较好的做法是避免在蓝图纯函数中输出数组属性; |
| CallInEditor | 可在实例上通过细节面板中调用此函数; |
| Category = "TopCategory\|SubCategory\|Etc" | 在蓝图编辑工具中显示指定函数的类别;使用 | 运算符定义嵌套类别; |
| BlueprintNativeEvent | 此函数旨在被蓝图覆盖掉,但也具有默认原生实现;用于声明名称与主函数相同的附加函数,但末尾添加了_Implementation,是写入代码的位置;如未找到任何蓝图覆盖,该自动生成的代码将调用 _Implementation 方法; |
| Client | 此函数仅在调用此函数对象的客户端上执行;用于声明名称与主函数相同的附加函数,但末尾添加了_Implementation;必要时,此自动生成的代码将调用 _Implementation 方法; |
| Server | 此函数仅在服务器上执行;用于声明名称与主函数相同的附加函数,但末尾添加了 _Implementation,是写入代码的位置;必要时,此自动生成的代码将调用 _Implementation 方法; |
| WithValidation | 用于声明名称与主函数相同的附加函数,但末尾需要添加_Validate;此函数使用相同的参数,但是会返回bool,以指示是否应继续调用主函数; |
| CustomThunk | UnrealHeaderTool 代码生成器将不为此函数生成thunk,用户需要自己通过 DECLARE_FUNCTION 或 DEFINE_FUNCTION 宏来提供thunk; |
| Exec | 此函数可从游戏内控制台执行;仅在特定类中声明时,Exec命令才有效; |
| NetMulticast | 此函数将在服务器上本地执行,也将复制到所有客户端上,无论该Actor的 NetOwner 为何; |
| Reliable | 此函数将通过网络复制,并且一定会到达,即使出现带宽或网络错误;仅在与Client或Server配合使用时才有效; |
| Unreliable | 此函数将通过网络复制,但可能会因带宽限制或网络错误而失败;仅在与Client或Server配合使用时才有效; |
| SealedEvent | 无法在子类中覆盖此函数;SealedEvent关键词只能用于事件;对于非事件函数,请声明为static或final,以密封它们; |
| ServiceRequest | 此函数为RPC(远程过程调用)服务请求,这意味着 NetMulticast 和 Reliable; |
| ServiceResponse | 此函数为RPC服务响应,这意味着 NetMulticast 和 Reliable; |
Metadata Specifiers
声明类、接口、结构体、枚举、枚举值、函数,或属性时,可添加 元数据说明符 来控制其与引擎和编辑器各方面的相处方式;每一种类型的数据结构或成员都有自己的元数据说明符列表;
注,Metadata只存在于编辑器中,不要编写能够访问到Metadata的游戏逻辑;
| AdvancedDisplay="Parameter1, Parameter2, .." | 以逗号分隔的参数列表将显示为高级引脚(需UI扩展); |
| AdvancedDisplay=N | 用一个数字替代 N ,第N之后的所有参数将显示为高级引脚(需UI扩展);如:'AdvancedDisplay=2' 将把前两个之外的所有参数标记为高级; |
| ArrayParm="Parameter1, Parameter2, .." | 说明 BlueprintCallable 函数应使用一个Call Array Function节点,且列出的参数应被视为通配符数组属性; |
| ArrayTypeDependentParams="Parameter" | 使用 ArrayParm 时,此说明符将指定一个参数,其将确定 ArrayParm 列表中所有参数的类型; |
| AutoCreateRefTerm="Parameter1, Parameter2, .." | 如列出参数(由引用传递)的引脚未连接,其将拥有一个自动创建的默认项;这是蓝图的一个便利功能,经常在数组引脚上使用; |
| BlueprintAutocast | 仅能由来自蓝图函数库的静态 BlueprintPure 函数使用;Cast节点将根据返回类型和函数首个参数的类型来自动添加; |
| BlueprintInternalUseOnly | 此函数是一个内部实现细节,用于实现另一个函数或节点;其不会直接在蓝图图表中公开; |
| BlueprintProtected | 此函数只能在蓝图中的拥有对象上调用;其无法在另一个实例上调用; |
| CallableWithoutWorldContext | 用于拥有一个 WorldContext 引脚的 BlueprintCallable 函数,说明函数可被调用,即使其类不实现 GetWorld 函数也同样如此; |
| CommutativeAssociativeBinaryOperator | 说明 BlueprintCallable 函数应使用Commutative Associative Binary节点,此节点缺少引脚命名,但拥有一个创建额外输入引脚的 添加引脚(Add Pin) 按钮; |
| CompactNodeTitle="Name" | 说明 BlueprintCallable 函数应在压缩显示模式中显示,并提供在该模式中显示的命名; |
| CustomStructureParam="Parameter1, Parameter2, .." | 列出的参数都会被视为通配符; |
| DefaultToSelf | 用于 BlueprintCallable 函数,说明对象属性的命名默认值应为节点的自我情境; |
| HideSelfPin | 隐藏用于指出函数调用所处对象的self引脚;self引脚在与调用蓝图的类兼容的 BlueprintPure 函数上为自动隐藏状态;这通常与 DefaultToSelf 说明符共用; |
| DeprecatedFunction | 蓝图对此函数进行引用时将引起编译警告,告知用户函数已废弃;可使用 DeprecationMessage 元数据说明符添加到废弃警告消息(如提供说明如何替代已废弃的函数); |
DeprecationMessage="Message Text" | 如果函数已废弃,尝试编译使用此函数的蓝图时,其将被添加到标准废弃警告; |
| DeterminesOutputType="Parameter" | 函数的返回类型将根据连接到命名参数引脚的输入动态更改;该参数应该是一个模板类型,比如 TSubClassOf<X> 或 TSoftObjectPtr<X>,其中函数的原始返回类型是 X* 或带有 X* 作为值类型的容器,比如 TArray<X*>; |
| DevelopmentOnly | 被标记为 DevelopmentOnly 的函数只会在Development模式中运行。这适用于调试输出之类的功能(但其不应存在于发布产品中); |
| DisplayName="Blueprint Node Name" | 此节点在蓝图中的命名将被此处提供的值所取代,而非代码生成的命名; |
| ExpandEnumAsExecs="Parameter" | 用于 BlueprintCallable 函数,说明应为参数使用的枚举中的每个条目创建一个输入执行引脚;命名参数必须是引擎通过 UENUM 标签识别的一个列举类型; |
| ForceAsFunction | 将没有来自事件的返回值的 BlueprintImplementableEvent 更改为函数; |
| HidePin="Parameter" | 用于 BlueprintCallable 函数,说明参数引脚应从用户视图中隐藏;注:使用此方式每个函数只能隐藏一个参数引脚; |
| InternalUseParam="Parameter" | 与 HidePin 相似,这将在用户视图中隐藏命名参数的引脚,只能用于一个函数的一个参数; |
| KeyWords="Set Of Keywords" | 指定在搜索此函数时可使用的一套关键词,如合适放置节点在蓝图图表中调用函数; |
| Latent | 说明一个延迟操作,延迟操作拥有类型为 FLatentActionInfo 的一个参数,此参数由 LatentInfo 说明符命名; |
| LatentInfo="Parameter" | 用于延迟 BlueprintCallable 函数,说明哪个参数是LatentInfo参数; |
| MaterialParameterCollectionFunction | 用于 BlueprintCallable 函数,说明应使用材质覆盖节点; |
| NativeBreakFunc | 用于 BlueprintCallable 函数,说明函数应以标准Break Struct节点的方式进行显示; |
| NotBlueprintThreadSafe | 只在蓝图函数库中有效,此函数将被视为拥有类的整体 BlueprintThreadSafe 元数据的一个例外; |
| ShortToolTip="Short tooltip" | 完整提示文本过长时使用的简短提示文本,如父类选取器对话; |
| ToolTip="Hand-written tooltip | 覆盖从代码注释自动生成的提示文本; |
| UnsafeDuringActorConstruction | 在Actor构造时调用此函数并非安全操作; |
| WorldContext="Parameter" | 由 BlueprintCallable 函数使用,说明哪个参数决定运算正在发生的World; |
| ScriptName="DisplayName" | 在将此类、属性或函数导出到脚本语言时使用的名称;可以包含以启用的名称作为以分号分隔的额外条目; |
Function Parameter Specifiers
| Out | 声明由引用传递的参数,使函数对其进行修改; |
| 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=(MetaTag1="Value1", MetaTag2, ..), SpecifierY)
添加Metadata Specifiers到枚举类型内的特定值,可将 UMETA 标签添加到值本身;
UENUM()
enum class EMyEnum : uint8
{
// DefaultValue Tooltip
DefaultValue = 0 UMETA(MetaTag1="Value1", MetaTag2, ..),
// ValueWithoutMetaSpecifiers Tooltip
ValueWithoutMetaSpecifiers,
// ValueWithMetaSpecifiers Tooltip
ValueWithMetaSpecifiers UMETA((MetaTag1="Value1", MetaTag2, ..),
// FinalValue Tooltip
FinalValue (MetaTag1="Value1", MetaTag2, ..)
};
四,Unreal Smart Pointer Library
虚幻智能指针库 为C++11智能指针的自定义实现,旨在减轻内存分配和追踪的负担;该实现包括行业标准 共享指针(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
虚幻智能指针库提供多个助手类和函数,以便使用智能指针时更加容易、直观;
| TSharedFromThis | 从TSharedFromThis派生类,添加AsShared or SharedThis函数;此类函数可获取对象的 TSharedRef; |
MakeShared、MakeShareable | 在常规C++指针中创建共享指针;
|
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 TSharedFromThis<FMyBaseClass>
{
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.
TSharedRef<FMyBaseClass> ThisAsSharedRef = AsShared();
// RegistryObject expects a TSharedRef<FMyBaseClass>, or a TSharedPtr<FMyBaseClass>. 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<> - TSharedRef<FMyBaseClass> in this example.
// SharedThis(this) will return a TSharedRef with the type of 'this' - TSharedRef<FMyDerivedClass> in this example.
// The SharedThis() function is only available in the same scope as the 'this' pointer.
TSharedRef<FMyDerivedClass> AsSharedRef = SharedThis(this);
// RegistryObject will accept a TSharedRef<FMyDerivedClass> 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(TSharedRef<FMyBaseClass>);
};
不要在构造函数中调用 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.
TSharedPtr<FDragDropOperation> Operation = DragDropEvent.GetOperation();
// We can now cast with StaticCastSharedPtr.
TSharedPtr<FAssetDragDropOp> DragDropOp = StaticCastSharedPtr<FAssetDragDropOp>(Operation);
Thread Safety
通常仅在单线程上访问智能指针的操作才是安全的。如需访问多线程,请使用智能指针类的线程安全版本:
-
TSharedPtr<T, ESPMode::ThreadSafe> -
TSharedRef<T, ESPMode::ThreadSafe> -
TWeakPtr<T, ESPMode::ThreadSafe> -
TSharedFromThis<T, ESPMode::ThreadSafe>
由于原子引用计数,此类线程安全版本比默认版本稍慢,但其行为与常规C++指针一致:
-
读取和复制固定为线程安全;
-
写入和重置须同步后才安全;
注,如多线程永不访问指针,可通过避免使用线程安全版本获得更好性能;
提示和限制
-
避免将数据作为
TSharedRef或TSharedPtr参数传到函数,此操作将因取消引用和引用计数而产生开销;相反,建议将引用对象作为const &进行传递; -
可将共享指针向前声明为不完整类型;
-
共享指针与虚幻对象(
UObject及其派生类)不兼容;引擎具有UObject管理的单独内存管理系统,两个系统未互相重叠;
289



被折叠的 条评论
为什么被折叠?



