1.table有4种基本操作:读,写,迭代和获取长度。
lua中没有删除操作而是将对应键位的值设置为nil.
lua的内部定义是在lobject.h
</pre><pre code_snippet_id="580775" snippet_file_name="blog_20150115_1_6202329" name="code" class="python"><pre name="code" class="cpp">/* ** Tables */ typedef union TKey { struct { TValuefields; struct Node *next; /* for chaining */ } nk; TValue tvk; } TKey; typedef struct Node { TValue i_val; TKey i_key; } Node;
<pre name="code" class="cpp">typedef struct Table { CommonHeader; lu_byte flags; /* 1<<p means tagmethod(p) is not present */ lu_byte lsizenode; /* log2 of size of `node' array */ (哈希表的长度) struct Table *metatable; (存储表对应的metatable) TValue *array; /* array part */ (数组) Node *node; (用来指向哈希表的指针) Node *lastfree; /* any free position is before this position */ (用来获取hash表中最后一个nil的位置,hash表中插入值) GCObject *gclist; int sizearray; /* size of `array' array */ (数组的长度) } Table;
从后面的表的获取长度,读写和迭代中,都可以看出lua中表的存储是分为两个部分:一个是数组部分,一个是哈希表。相应指针,和对应长度如代码中注释。
table中的基本相关操作c实现都在ltable.c中.
LUAI_FUNC Table *luaH_new (lua_State *L);
创建一个新的table 分配内存空间和对成员变量初始化。
LUAI_FUNC void luaH_free (lua_State *L, Table *t);
释放内存,先释放hash表部分,后释放数组部分。
LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize)
当需要开辟新的内存的时候,
LUAI_FUNC void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize);
是上面函数的具体实现。
LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key);
向lua中hash表部分插入一个新的key,插入的方式先查找hash表中,该建的主位置是不是有值,如果有值得话,先看该值的主位置是不是在这个Index上,如果是的话,新插入的key通过再散列找到下一个值为空的位置插入。如果它不是主位置,那么新插入的剑插入该位置,替换出来的值会放到其他位置,如果该位置没有值的话,那么就直接插入。
LUAI_FUNC int luaH_getn (Table *t);
获取长度,先找表中数组部分,如果数组部分有值的话,就返回数组部分的长度,如果数组部分没有值,就取hash表部分的长度
LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
lua通过这个函数实现table的递归,通过上一个键,来找到下一个键值对。先查找数组部分,如果没有再查找哈希表部分。其中首先通过finxdindex 根据传入的key找到对应的所在数组部分的位置,或者是放到所在hash表部分的索引,
2. 除了基础操作部分,lua还用c实现了直接操作table功能来提供给lua中进行使用。Table Manipulation在lua官方文档中这样写道:这个库为table的操作提供了一般的方法,它提供了在table中所有他得方法,记住,当一个操作需要table的长度的时候,这个table需要是一个当前本身的队列或者有一个__len
的元方法,所有方法都忽略在table中提供非数值的key作为参数。因为效率的原因,所有的通过这些方法对table访问执行都是未加工的(raw)
其中存储函数地址数组
</pre><pre code_snippet_id="580775" snippet_file_name="blog_20150115_3_4420509" name="code" class="python"><pre name="code" class="cpp">static const luaL_Reg tab_funcs[] = { {"concat", tconcat}, #if defined(LUA_COMPAT_MAXN) {"maxn", maxn}, #endif {"insert", tinsert}, {"pack", pack}, {"unpack", unpack}, {"remove", tremove}, {"sort", sort}, {NULL, NULL} };
maxn 函数,其中用到了luaH_next 查找table中所有正数key值中最大的key值,如果不存在key为正数的元素返回0,包括数组和hash表部分
tinsert 函数 在表的某个位置插入一个元素。
tremove 函数 移除某一个元素,从pos位置开始 通过t[pos] = t[pos+1] 将前面的元素覆盖掉。
tconcat 函数 table中元素全都是string类型的,将他们用指定的连接符连成一个字符串
pack 函数 返回一个新的table 通过数组存储对应的值
unpack函数 返回table的元素,这个方法等同于 return list[i], list[i+1], ···, list[j] 默认是 1 到 #table
sort函数 对table中元素进行排序,可以通过设置比较器来设置排序规则,如果没有给出的话,那么就会是使用<号来代替。同c++中快速排序.
由此可见 lua5.2中已经将table.getn这个函数去掉。之前看书和其他人的博客总是找不到这个函数用法。。。。