轻量级用户数据,与重量级用户数据一样,是用户数据的一种形式,用户数据是 Lua 中的基本数据类型之一 [1]。轻量级用户数据的特点如下:
- 轻量级用户数据和重量级用户数据的名字具有欺骗性,它们都具有属性
type(x) == 'userdata'
,但这两类用户数据在行为上却有很大不同 [1],如下所述。
- 轻量级用户数据表示指向物理内存地址的单个指针 (void *),通常是 32 位或 64 位值,具体取决于平台。轻量级用户数据旨在将 C 指针存储在 Lua 中(注意:Lua 数字可能适合也可能不适合此目的,具体取决于平台上的数据类型)。
- 重量级用户数据表示在 Lua 的内存中分配的、由 Lua 管理的可变字节区域(垃圾回收)。这是 Lua 中唯一允许您直接从 C(通过用户数据的指针)进行读写而不使用 C API 的内存。
- 轻量级用户数据具有值的语义,而重量级用户数据具有对象的语义。对象具有唯一的标识 [2]:使用相同数据构造的两个重量级用户数据始终是可区分的(例如,
rawequal
将通过内存地址区分它们);两个这样构造的轻量级用户数据将永远不可区分,因为它们是按值比较而不是按地址比较。
- 轻量级用户数据(与重量级用户数据不同)不会被垃圾回收。 LuaImplementations 通常将每个轻量级用户数据放入单个寄存器中,并按值复制它们,而重量级用户数据则在堆上分配,并通过引用(指针)传递。
- 相等性:如果
x
是一个轻量级用户数据,那么 x == y
当且仅当 y
是一个表示相同指针的轻量级用户数据。轻量级用户数据可以用作表键,在这种情况下,x == y
意味着 t[x]
和 t[y]
指向同一个表值(但不一定意味着 t[x] == t[y]
,因为 NaN ~= NaN)。__eq
元方法对轻量级用户数据没有影响(注意:手册对此并不明确 [1])。
- 轻量级用户数据(与重量级用户数据不同)没有每个值的元表。所有轻量级用户数据共享同一个元表,默认情况下该元表未设置(
nil
)。
-
tostring(x)
通常以十六进制表示法显示指针,但这特定于 LuaImplementations。
一些有趣的点
- 将 C 指针映射到 Lua 值的一种常见技术是将该指针的轻量级用户数据存储为注册表表中的键。 [参考手册,3.5]。请记住,这些映射不会自动进行垃圾回收 [3],您可能希望使用弱表而不是注册表(默认情况下不是弱表,但弱表可以存储在其中)。
- 有些人将句柄而不是指针表示为轻量级用户数据 [4]。也可以在其中表示其他数据 [5]。注意不要以可能冲突的方式混合指针和非指针用户数据(例如,将两者都存储在注册表表中)。
- 轻量级用户数据是通过 C API 使用 [lua_pushlightuserdata] 创建的。开箱即用,Lua 没有提供从 Lua 创建轻量级用户数据的方法。
- 关于轻量级用户数据的单页摘要在 [1] 中提供。
--DavidManura
另请参阅
- [1] ProgrammingInLua?,第 28.5 节“轻量级用户数据”。
最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2011 年 8 月 4 日凌晨 3:56 GMT (差异)