lua弱引用表weak table的用途

2021-10-06 02:44:43 字數 4840 閱讀 1893

目錄

1.簡介

2.定義

3.示例

示例1示例2

4.應用

1.記憶(快取)函式

示例1示例2

2.設定表的預設值

1)lua的gc預設是自動**的,當乙個物件的引用計數為0時,它就會被gc所**。

2)lua中的表預設是強引用的,當你把某個物件放入表中時,就是生成乙個對它的強引用(物件的引用計數+1),在物件的引用計數沒有為0之前不會被gc**;

3)如果把乙個表宣告為弱引用,則當把某個物件放如表中時,生成乙個弱引用物件不會被引用計數,可以理解為引用計數+0);如果乙個物件只被弱引用表所引用(物件的引用計數為0),則會被下一次gc自動**

所以弱引用表weak table的用途一般都是出於gc考慮的

注意:以上所指物件不包括值型別:number、boolean

可以通過重寫元方法__mode來定義乙個表為弱引用表weak table,它包含三個值:"k"、"v"、"kv",參見如下:

k標記表的key為弱引用

v標記表的value為弱引用

kv同時標記表的key和value為弱引用

t = {}

--標記表t的key為弱引用

setmetatable(t, )

key1 =

key2 =

t[key1] = 1

t[key2] = 2

--手動呼叫gc來測試

collectgarbage()

for k, v in pairs(t) do

print(k.name, v)

endprint("-----------------------------------------")

key1 = nil

--手動呼叫gc來測試

collectgarbage()

for k, v in pairs(t) do

print(k.name, v)

end

輸出如下:

key1	1

key2 2

-----------------------------------------

key2 2

可以看到當key1 = nil 並手動呼叫gc後,key1所佔的記憶體被**了,t中也訪問不到key1了

point = 

function point:new(x, y)

local o = {}

setmetatable(o, self)

self.__index = self

o.x = x

o.y = y

return o

endcollectgarbage("collect")

t = {}

--標記表t的value為弱引用

setmetatable(t, )

arr = {}

--生成100個point物件,並對arr和t賦值

for i = 1, 100 do

arr[i] = point:new(i, 10 - i)

t[i] = arr[i]

endcollectgarbage("collect")

for i = 1, 100 do

arr[i] = nil

endprint("before memory : "..collectgarbage("count"))

collectgarbage("collect")

print("after memory : "..collectgarbage("count"))

print("t.length : "..#t..", arr.length : "..#arr)

輸出如下:

before memory : 40.8173828125

after memory : 29.0986328125

t.length : 0, arr.length : 0

可以看到:在arr的元素被設定為nil後,因為t的value是弱引用,所以arr的元素被gc所**,記憶體從40k降到了29k;

如果把 setmetatable(t, ) 標記弱引用的這句去掉,則輸入如下:

before memory : 40.6201171875

after memory : 40.6201171875

t.length : 100, arr.length : 0

可以看到arr的元素引用被設定為nil後,但是t還是強引用表,所以這100個元素的記憶體沒有被釋放

空間換時間是程式設計中常用的一種方式,我們可以用犧牲一點記憶體為代價來提公升效能。參見如下:

--記憶(快取)函式

function memoize(func)

local mem = {}

setmetatable(mem, )

return function(parm)

local r = mem[parm]

if r == nil then

r = func(parm)

mem[parm] = r

endreturn r

endend--模擬乙個複雜的計算過程

function getresult(x)

for i = 1, 10000 do

x = x + 1

endreturn x

end--重新定義函式的記憶化(快取)版本

getresult = memoize(getresult)

begintime = os.clock()

result = 0

for i = 1, 10000 do

result = getresult(1)

endprint("result : "..result..", time : "..(os.clock() - begintime))

輸出如下:

result : 10001, time : 0.001
再對比一下沒有用記憶函式的版本 : getresult = memoize(getresult)  ,輸出如下:

result : 10001, time : 0.726
可以看到採用記憶函式的後,對於大量的頻繁呼叫,在引數變化不大的情況下,效能有很大的提公升

lua中load函式(或舊版本的loadstring,5.2以上版本已刪除)一般用於動態執行外部**;因為是動態執行,所有每次執行前都會先編譯一次,那產生的效能問題就是必須要考慮的了。所以可以用記憶函式包裝後再使用,對於相同的字串就不會每次都編譯,提高了執行效率, 參見如下:

function memoize(func)

local mem = {}

setmetatable(mem, )

return function(parm)

local r = mem[parm]

if r == nil then

r = func(parm)

mem[parm] = r

endreturn r

endend--重新定義函式的記憶化版本

load = memoize(load)

starttime = os.clock()

result = 0

for i = 1, 1000000 do

load("result = result + 1")()

endprint("result = "..result..", time = "..(os.clock() - starttime))

輸出如下:

result = 1000000, time = 0.087
對比一下沒有用記憶函式的版本 : load = memoize(load),輸出如下:

result = 1000000, time = 1.823
可以看到採用記憶函式的後效能有很大的提公升

參見如下:

--設定表的預設值

function setdefault()

local mem = {}

setmetatable(mem, )

return function(t, data)

setmetatable(t, )

local r = mem[t]

if r == nil then

r = data

mem[t] = r

endreturn r

endend--獲取乙個setdefault的閉包函式

setdefault = setdefault()

key1 = {}

key2 = {}

setdefault(key1, 100)

setdefault(key2, )

print(key1.default)

print(key2.default.name)

輸出如下:

100

default value table

如上可以看到,我們可以對乙個表t設定乙個預設的資料data。可以理解為乙個字典dictionary,表t是key,data是value;但是當表t == nil,觸發gc**後,它會自動從字典中消失,不用單獨對字典做維護

lua的弱弱引用表

lua有gc。細節無需太關注,知道些主要的即可。能local就一定不要global 還有在陣列裡的物件,除非顯式 nil,否則非常難 只是能夠用弱引用表來告訴gc。外部引用為0,就不要管我,請del it。weak table是通過元表實現,元表裡的 mode欄位包括k或者v k表示key為弱引用 ...

Lua教程(十三) 弱引用table

lua採用了基於垃圾收集的記憶體管理機制,因此對於程式設計師來說,在很多時候記憶體問題都將不再困擾他們。然而任何垃圾收集器都不是萬能的,在有些特殊情況下,垃圾收集器是無法準確的判斷是否應該將當前對程式設計客棧象清理。這樣就極有可能導致很多垃圾物件無法被釋放。為了解決這一問題,就需要lua的開發者予以...

LUA表的引用理解

lua中引用型別都是分配在堆上的 因此,我們在使用lua的table時,可盡可能的使用表的引用,而不需要拷貝表裡的元素 比如,通過rpc協議傳來乙個表a,我們想要快取這個表,只需要儲存該錶的引用 而不需要再重新生成乙個新錶然後將表a的元素乙個個拷過來 function func local t 生成...