![]() |
VOOZH | about |
nim語言的引用和其他語言的指針有點相似
可以提供一種「多對一」的關係
這就意味著不同的引用可以指向同一個內存位置
nim區分可被追蹤的引用和不可被追蹤的引用
不可被追蹤的引用又稱為指針
可被追蹤的引用可以被垃圾回收器回收
不可被追蹤的引用指向手動分配的對象,或其他地方創建出來的一塊內存區域
這也就是說,不可被追蹤的引用是不安全的
對於某些底層操作,不可被追蹤的引用有其存在的必要
可被追蹤的引用使用ref關鍵字定義,
不可被追蹤的引用使用ptr關鍵字定義
空下標的方括號可以用來解引用
addr方法可以返回一個實例的地址
對於一個地址來說,它始終是一個不可追蹤的引用
所以addr方法也是一個不安全的方法。
.操作符和操作符可以隱式執行,先來看一下下面的代碼
type Node = ref NodeObj NodeObj = object le, ri: Node data: int var n: Node new(n) n.data = 9在上面的代碼中,不需要寫成n.data,
因為方括號操作符已經隱式執行了
事實上nim官方也強烈不建議寫成n.data
另外,自動解引用操作也直接作用於一個方法的調用
但目前看來,還必須加上{.experimental.}配置節
請看如下示例代碼:
{.experimental.} proc depth(x: NodeObj): int = ... var n: Node new(n) echo n.depth也不用寫成n.depth
為了簡化類型檢查,nim語言不支持遞歸元組
下面的寫法是錯誤的
type MyTuple = tuple[a: ref MyTuple]同樣 T = ref T 也是錯誤的
如果一個對象只能出現其引用類型,不能出現其值類型
那麼可以用如下方法完成:
type Node = ref object le, ri: Node data: int可以使用內置的new方法為一個可被追蹤的對象分配內存
可以使用alloc、dealloc和realloc來應對不可被追蹤的對象
這些方法的具體信息都可以在system類庫的說明文檔中找到
如果一個引用指向為空,那麼這個引用的值就是nil
如果你碰到一個不可被追蹤的對象裡面包含一個可被追蹤的對象(或者是一個字符串、又或者是一個sequences)
那麼就需要特別留意了,為了讓一切都正常釋放,
你必須在釋放不可被追蹤的對象之前,使用內置的GCunref方法處理一下這個對象的那些特殊屬性
請看下面的示例代碼:
type Data = tuple[x, y: int, s: string] # 在內存堆上創建一個不可被追蹤的對象: var d = cast[ptr Data](alloc0(sizeof(Data))) # create a new string on the garbage collected heap: d.s = "abc" # 告訴 GC 這個string類型的屬性已經沒有存在的必要了: GCunref(d.s) # 釋放不可被追蹤的對象: dealloc(d)如果不用GCunref方法處理一下對象的字符串屬性,
那麼這個字符串所占用的內存將永遠不會被釋放
上面的代碼同時也展示了:
怎麼獲得一個類型的size
alloc0方法創建一個沒有類型的指針
cast方法可以繞過類型系統,讓指針具有類型ptr Data
只有在非常必要的時候再用cast方法,因為他會破壞類型安全,導致不可預知的BUG