Nim 中的引用和指針


引用和指針

    引用是介紹多對一關係的一種方式。這意味着不同的引用可以指向和修改相同的內存單元。在Nim中分爲跟蹤引用和非跟蹤引用(反跟蹤)。非跟蹤引用也叫做指針。跟蹤引用指向一個垃圾收集堆上的對象,反跟蹤指向手動分配的對象或內存中其他地方的對象。因此反跟蹤引用是不安全的。然而對於某些低級操作(訪問硬件)反跟蹤引用是不可避免的。

    引用用 ref 關鍵字聲明,指針用 ptr 關鍵字聲明。

    方括號[] 能夠訪問存取引用指向的數組、字符串、序列的值。 . 運算符能夠訪問存取元組、對象的域。

  創建一個新的追蹤對象,要用到內置函數new()。爲了處理反追蹤內存函數alloc(),dealloc(),realloc()函數可以使用。


引用:

type
  Node = ref NodeObj
  NodeObj = object
    le, ri: Node
    data: int

var
  n: Node
new(n)
n.data = 5
# no need to write n[].data; in fact n[].data is highly discouraged!
echo n.data

type 
  TnodeArr = array[10,Node]
var myNodeArr:TnodeArr
for i in 0..5:
  new(myNodeArr[i])
  myNodeArr[i].data = i

myNodeArr[0].ri = myNodeArr[1]
myNodeArr[5].ri = myNodeArr[0]
myNodeArr[0].le = myNodeArr[5]
myNodeArr[5].le = myNodeArr[4]
  
for i in 1..4:
  myNodeArr[i].ri = myNodeArr[i+1]
  myNodeArr[i].le = myNodeArr[i-1]

for i in 0..5:
  echo myNodeArr[i].data,"==>",myNodeArr[i].le.data,"    ",myNodeArr[i].ri.data

輸出:

5
0==>5    1
1==>0    2
2==>1    3
3==>2    4
4==>3    5
5==>4    0


指針:

type
  Data = tuple[x, y: int, s: string]

# allocate memory for Data on the heap:
var d = cast[ptr Data](alloc0(sizeof(Data)))

# create a new string on the garbage collected heap:
d.s = "abc"
echo d[]

# tell the GC that the string is not needed anymore:
GCunref(d.s)

# free the memory:
dealloc(d)

輸出:
(x: 0, y: 0, s: abc)


int 在內存中的存儲

import strutils

type
  myint = ref int
  
var 
  refvar1:myint
  refvar2:myint
  var1:int
  var2:int

var1 = 6
var2 = 6

new refvar1                     #注意使用 引用前要 new
new refvar2            

echo repr(var1)             #repr 返回的是 變量 var1 的字符串表達。 如果是整形,返回整形的值,如果是字符串,返回字符串存儲位置和字符串。
echo repr(refvar1)

refvar1 = cast[myint](addr(var1))                #addr 返回的是 變量var1在內存中的地址。    此時引用指向了變量 var1 的地址。

echo BiggestInt(cast[int](addr(var1))).toHex(12)    #把var1 的地址轉換成十六進制數輸出。
echo repr(refvar1)               #ref 0x624e00 --> 6     表示引用refvar1 指向變量地址爲 0x624e00的變量, 變量var1 的內容是 6.

refvar2 = cast[myint](addr(var2))

echo BiggestInt(cast[int](addr(var2))).toHex(12)
echo repr(refvar2)

string 在內存中存儲

import strutils

var
  var1 = "yrs"
  refvar1:ref string

echo BiggestInt(cast[int](addr(var1))).toHex(12)      #var1 的地址
echo BiggestInt(cast[int](var1)).toHex(12)            #var1 的內容
echo repr(var1)                                     #var1 的內容爲存放 字符串 "yrs" 的地址。

new refvar1

refvar1 = cast[ref string](addr(var1))             #此時引用refvar1 的內容是 var1 的地址,也就是refvar1 指向 var1.
echo repr(refvar1)                          #ref 0x624dd0 --> 0x7f3c2808d050"yrs"  代表的意思是:引用refvar1 的內容爲var1的地址 0x624dd0,
                                          #0x7f3c2808d050 是var1 的內容, 也是存儲字符串 "yrs" 的地址。
echo refvar1[]                        #[]是字符串,序列等的解引用,  . 是對 對象域的解引用。

用一張圖片來表示:


由此可見int 和 string 在內存中存儲是不一樣的。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章