只有向table插入数据时,才有可能触发rehash

table只有在满的情况下,继续插入的数据的时候,才会触发rehash。如果将一个table中的数据全部设置为nil,后续没有插入操作,这个table的大小会继续保持原状,不会收缩,占用的内存不会释放。 除非不停地向table中写入nil,写入足够多的次数后,重新触发rehash,才会发生收缩:

a = {}
lim = 10000000

for i = 1, lim do a[i] = i end            --  create a huge table
print(collectgarbage("count"))            --> 196626

for i = 1, lim do a[i] = nil end          --  erase all its elements
print(collectgarbage("count"))            --> 196626,不会收缩

for i = lim + 1, 2*lim do a[i] = nil end  --  create many nil element
print(collectgarbage("count"))            --> 17,添加足够多nil之后才会触发rehash

不要用这种方式触发rehash,如果想要释放内存,就直接释放整个table,不要通过清空它包含的数据的方式进行。

将table中的成员设置为nil的时候,不触发rehash,是为了支持下面的用法:

for k, v in pairs(t) do
  if some_property(v) then
    t[k] = nil    -- erase that element
  end
end

如果每次设置nil都触发rehash,那么上面的操作就是一个灾难。

清理table中的所有数据时,用pairs,不要用next

如果要在保留table变量的前提下,清理table中的所有数据,一定要用pairs()函数,不能用next()

next()函数是返回中的table第一个成员,如果使用下面方式,next()每次从头开始查找第一个非nil的成员:

while true do
	local k = next(t)
	if not k then break end
	t[k] = nil
end

正确的做法是用pairs

for k in pairs(t) do
	t[k] = nil
end