第一版是為 Lua 5.0 編寫的。雖然在很大程度上仍然適用於後續版本,但仍有一些差異。
第四版針對 Lua 5.3,可在 Amazon 和其他書店購買。
購買本書,您還可以協助 支援 Lua 專案。
![]() |
用 Lua 程式設計 | ![]() |
第二部分。表格和物件 第 17 章。弱表格 |
Lua 具有自動記憶體管理功能。程式只會建立物件(表格、函式等);沒有用於刪除物件的函式。Lua 會使用垃圾回收自動刪除成為垃圾的物件。這讓您免於承擔記憶體管理的大部分負擔,更重要的是,讓您免於承擔與該活動相關的大部分錯誤,例如懸浮指標和記憶體外洩。
與其他一些收集器不同,Lua 的垃圾收集器不會出現循環問題。使用循環資料結構時,您不需要採取任何特殊動作;它們會像其他資料一樣被收集。儘管如此,有時即使是更智慧的收集器也需要您的協助。沒有垃圾收集器可以讓您忘記所有關於記憶體管理的煩惱。
垃圾收集器只能收集它確定為垃圾的內容;它無法知道您認為是什麼垃圾。一個典型的範例是堆疊,它使用陣列和指標實作到頂端。您知道陣列的有效部分只到頂端,但 Lua 不知道。如果您透過遞減頂端來彈出元素,陣列中留下的物件對 Lua 來說並非垃圾。同樣地,儲存在全域變數中的任何物件對 Lua 來說都不是垃圾,即使您的程式永遠不會再使用它。在這兩種情況下,都由您(即您的程式)將 nil 指定給這些位置,以便它們不會鎖定其他已釋放的物件。
但是,僅清理您的參考並不總是足夠的。有些結構需要您和收集器之間額外的協作。一個典型的範例發生在您想要在程式中保留某種類型所有現存物件(例如檔案)的集合時。這似乎是一項簡單的任務:您所要做的就是將每個新物件插入集合中。但是,一旦物件進入集合,它就永遠不會被收集!即使沒有其他人指向它,集合也會指向它。Lua 無法知道這個參考不應阻止回收物件,除非您告訴 Lua。
弱表格是您用來告訴 Lua 參考不應阻止回收物件的機制。弱參考是垃圾收集器不考慮的物件參考。如果指向物件的所有參考都很弱,則會收集物件並以某種方式刪除這些弱參考。Lua 將弱參考實作為弱表格:弱表格是一個其中所有參考都很弱的表格。這表示,如果物件只保存在弱表格中,Lua 最終會收集物件。
表格具有鍵和值,且兩者都可能包含任何類型的物件。在正常情況下,垃圾回收器不會回收顯示為可存取表格的鍵或值的物件。亦即,鍵和值都是強參照,因為它們會防止回收它們所參照的物件。在弱表格中,鍵和值可能是弱的。這表示有 3 種類型的弱表格:具有弱鍵的表格、具有弱值的表格,以及完全弱的表格(其中鍵和值都是弱的)。不論表格類型為何,當鍵或值被回收時,整個項目會從表格中消失。
表格的弱點由其元表的 __mode
欄位提供。此欄位的數值(如果存在)應為字串:如果字串包含小寫字母 `k
´,表格中的鍵就是弱的;如果字串包含小寫字母 `v
´,表格中的值就是弱的。以下範例雖然是人為的,但說明了弱表格的基本行為
a = {} b = {} setmetatable(a, b) b.__mode = "k" -- now `a' has weak keys key = {} -- creates first key a[key] = 1 key = {} -- creates second key a[key] = 2 collectgarbage() -- forces a garbage collection cycle for k, v in pairs(a) do print(v) end --> 2在此範例中,第二次指定
key = {}
會覆寫第一個鍵。當回收器執行時,沒有其他參照指向第一個鍵,因此它會被回收,而表格中對應的項目也會被移除。不過,第二個鍵仍錨定在變數 key
中,因此不會被回收。
請注意,只有物件可以從弱表格中回收。數值和布林值等值無法回收。例如,如果我們在表格 a
(來自我們之前的範例)中插入一個數字鍵,它永遠不會被回收器移除。當然,如果對應於數字鍵的值被回收,則整個項目會從弱表格中移除。
字串在此處呈現出細微差異:雖然字串可以回收,但從實作觀點來看,它們不像其他可回收物件。其他物件(例如表格和函式)會明確建立。例如,每當 Lua 評估 {}
時,它會建立一個新表格。每當它評估 function () ... end
時,它會建立一個新函式(實際上是一個閉包)。不過,當 Lua 評估 "a".."b"
時,它會建立一個新字串嗎?如果系統中已經有一個字串 "ab"
呢?Lua 會建立一個新字串嗎?編譯器可以在執行程式之前建立那個字串嗎?這並不重要:這些都是實作細節。因此,從程式設計師的觀點來看,字串是值,而不是物件。因此,就像數字或布林值一樣,字串不會從弱表格中移除(除非其關聯值被回收)。
版權所有 © 2003–2004 Roberto Ierusalimschy。保留所有權利。 | ![]() |