中EN
概念页

容器与字符串

Containers & Strings

更新于 2026-10-11 约 4 分钟UE5TArrayTMapFStringFNameFText

UE 不用 STL,而用自带的值类型容器:TArray(连续数组)、TMap/TMultiMap(哈希映射)和 TSet(哈希集合),都假定元素可按字节直接搬移。字符串分三种:FName 存索引、比较便宜,FText 用于可本地化的界面文本,FString 可以修改但开销最大。选错类型的代价主要是性能和本地化。

容器:值语义与内存布局

  • TArray 是最常用的容器,「快、省内存、安全」。它是值类型:拥有自己的元素,拷贝时复制全部元素、不共享状态,销毁时元素一并销毁;不应 new/delete 它,也不应继承它。模板参数是元素类型和可选的分配器 (allocator),默认分配器从堆上分配,并在容量不够时一次多分配几个元素的空间。(Array Containers in Unreal Engine)
  • Add 与 Emplace:Add 先构造一个临时对象再拷贝或移动进数组,Emplace 直接用参数在数组里构造。官方经验法则:平凡类型用 Add,其他类型用 Emplace;Emplace 永远不会比 Add 慢。(Array Containers in Unreal Engine)
  • TMap / TSet 基于哈希:键类型要提供 GetTypeHash 和 operator==(或自定义 KeyFuncs)。底层是稀疏数组,删除元素会留下空洞,之后新增的元素可能填进空洞,所以遍历顺序不可靠、元素在内存中也不连续。扩容时整块存储会重新分配,所以指向元素的指针可能失效。TMap 遇到重复键时用新值替换旧值;TMultiMap 则两个都保留。TSet 的增删查都是常数时间。(Map Containers in Unreal Engine、Set Containers in Unreal Engine)
  • 三者都假定元素是「可平凡搬移 (trivially relocatable)」的,扩容时直接按原始字节拷贝;元素里如果有指向自身内部的指针,这个假设会出问题。
容器结构顺序适用
TArray连续内存稳定绝大多数列表;遍历快、对缓存友好
TMap稀疏数组 + 哈希不保证按键查找
TSet稀疏数组 + 哈希不保证去重、判断是否存在

(表格依据上述三页归纳。)

三种字符串

类型原理用途注意
FName全局唯一字符串表;FName 只存索引和实例号,用哈希表做字符串到 FName 的转换资产名、骨骼名、标识符等需要频繁比较的字符串不区分大小写、不可变;== 只比较索引,「大量节省 CPU」
FText关联本地化数据所有面向玩家的文本与 FString 互转会丢失本地化数据
FString自带字符数组需要搜索、修改、拼接的字符串可修改,所以比另外两种更贵

(String Handling in Unreal Engine、FName in Unreal Engine、FText in Unreal Engine、FString in Unreal Engine)

转换的坑(官方原文标为「危险」):FString → FName 会丢信息,因为 FName 不区分大小写;FText → FString 对某些语言可能丢信息;FText 不能直接转成 FName,要先转 FString。FText::FromString 在编辑器构建中不会把文本标为文化无关 (culture invariant),保存到资产里的 FText 属性后仍可能变成可本地化文本;真正不需要本地化的文本用 AsCultureInvariant 或 INVTEXT。(FText in Unreal Engine)只想判断某个名字是否已在名称表里、又不想新增条目时,用 FName(TEXT("x"), FNAME_Find),不存在时得到 NAME_None。(FName in Unreal Engine)

实践建议

  • 界面上显示的字符串一律用 FText,否则后期本地化要返工。
  • 热路径里避免反复把 FString 构造成 FName(每次都要查哈希表);常用名字应缓存为静态 FName。
  • 容器作为 UPROPERTY 时,GC 才能看到里面的 UObject 引用,见 UObject 与反射系统、垃圾回收与对象生命周期。(与 GC 的关联依据已有页面。)
  1. Array Containers in Unreal Engine UE 5.8 文档
  2. Map Containers in Unreal Engine UE 5.8 文档
  3. Set Containers in Unreal Engine UE 5.8 文档
  4. String Handling in Unreal Engine UE 5.8 文档
  5. FString in Unreal Engine UE 5.8 文档
  6. FName in Unreal Engine UE 5.8 文档
  7. FText in Unreal Engine UE 5.8 文档

相关页面

游戏开发 · UE5智能指针与 TObjectPtrSmart Pointers & TObjectPtrUE 有两套对象寿命管理:普通 C++ 对象用引用计数智能指针(TSharedPtr/TSharedRef/TWeakPtr/TUniquePtr),UObject 由垃圾回收管理,不能放进这些智能指针。UE5 新增的 TObjectPtr 用来替代 UPROPERTY 里的 UObject 裸指针:编辑器构建中提供动态解析和访问跟踪,非编辑器构建中与裸指针表现相同。游戏开发 · UE5UObject 与反射系统UObject & Reflection System虚幻引擎 (Unreal Engine) 的对象基类是 UObject。在 C++ 类、属性、函数上加 UCLASS/UPROPERTY/UFUNCTION 等宏,再由构建前的预处理工具虚幻头文件工具 (Unreal Header Tool, UHT) 扫描头文件生成代码,引擎就能在运行时“看见”这些类型——这就是反射系统 (Reflection System)。垃圾回收、序列化、编辑器面板、蓝图、网络复制都建立在它之上。游戏开发 · UE5配置文件系统Configuration FilesUE 的 .ini 配置按类别(Engine、Game、Input……)分层加载:从引擎 Base 文件到项目 Default 文件,再到平台文件和用户文件,后加载的同名键覆盖先加载的。数组可以用 +、-、! 等运算符跨层增删。UCLASS(config=X) 加上 UPROPERTY(Config) 可以让类的默认值从 ini 自动读取;命令行 -ini: 可以临时覆盖。游戏开发 · UE5本地化LocalizationUE 的本地化以 FText 类型为中心,国际化(数字、日期、复数规则、文化回退)依赖 ICU 库。可本地化的文本由命名空间、键、源字符串三部分标识;本地化管线按目标 (Localization Target) 依次收集 (Gather) 到 manifest、翻译进各文化的 archive(通常经 PO 文件导出导入)、编译成运行时加载的 .locres。Localization Dashboard 是管理这条管线的推荐工具。游戏开发容器与哈希表Containers & Hash Tables容器的职责都是容纳和管理零个或多个元素,差别在于实现方式与取舍。GEA 概览了常见容器与操作、迭代器、大 O 复杂度与内存布局的综合考量,讨论引擎为何常自研容器、C++ 标准库 / Boost / Folly / Loki 的利弊,并重点讲了动态数组的增长策略与哈希表(开放哈希与封闭哈希、哈希函数、线性/二次探测、Robin Hood 哈希)。游戏开发字符串与唯一标识符Strings & Unique Identifiers字符串在 C/C++ 中只是字符数组,变长意味着要么硬编码长度上限、要么动态分配;比较和复制都是 O(n)。引擎内部大量用字符串做资源名和对象 ID,处理不当会严重拖慢游戏。GEA 的建议:运行时代码尽量避免字符串类,若用则了解其成本并按引用传递;路径类是值得专门做的例外;对象与资产的唯一标识用哈希字符串 ID(string id),兼得字符串的可读性与整数的比较速度。游戏开发游戏本地化与 UnicodeGame Localization & Unicode本地化(国际化,I18N)是把软件改编为其他语言版本,最好从第一天起规划并贯穿每个开发步骤。GEA 介绍了 Unicode 与 UTF-32/UTF-8/UTF-16/UCS-2 编码、char 与 wchart、Windows 的字符串 API 约定、主机上的选择,字符串之外的本地化问题,以及核心基础设施——字符串数据库 + 按 ID 查找当前语言字符串的运行时函数,并以 Naughty Dog 的本地化工具为例。游戏开发 · UE5垃圾回收与对象生命周期Garbage Collection & Object LifecycleUE 用标记-清除式的可达性分析管理 UObject 内存:从根集合 (Root Set) 出发沿反射可见的强引用遍历对象图,找不到的对象在下次垃圾回收 (Garbage Collection, GC) 时被删除。因此“谁持有 UPROPERTY 引用”决定了对象活多久;Actor 调用 Destroy() 只是请求销毁,真正释放仍取决于引用是否全部放开。

输入关键词开始搜索

滚轮或双指缩放 · 拖动平移 · 双击放大 / 还原