首页 > 代码库 > lua 中table的使用和分析

lua 中table的使用和分析

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这个函数去掉。之前看书和其他人的博客总是找不到这个函数用法。。。。

lua 中table的使用和分析