Edited at

nim ポインタについて

More than 1 year has passed since last update.


概要


  • nimのポインタについて

  • pointer, ptr, refとあるので調べてみた


検証


  • pointer, ptr, refをそれぞれどんな時に使うのか


    • pointer アドレスを扱う型

    • ptr [型] [型]のアドレスを扱う型


      • reprとかで値まで出力してくれる



    • ref [型] [型]をnewするための型



みたいな考え方で良さそう

ref型はnewでメモリを確保するので、参照されなくなったら解放される。(GCされる)

アドレス自体をなんかしたい場合はptrとかpointerを使う。(この2つはGCされない)

pointerはどの型のポインタでも良く(Cで言うvoid*)、参照先を取りたい時は明示的にキャストしなければならない。

procの中で引数で渡した変数の値を変更したいときとかも、

var intとかして渡せば、out引数にできるので、わざわざポインタにして渡す必要とかはない。


example.nim

proc foo(num: var int) =

num = 100

foo(num)
echo num # 100



検証コード


example.nim

var

num: int = 300
num_ptr_1: ptr int = num.addr
num_ptr_2: pointer = num.addr
num_ref: ref int

echo repr(num_ptr_1)

echo repr(num_ptr_2)

echo repr(cast[ptr int](num_ptr_2))

proc ref_test(num: ref int) =
echo repr(num)

num_ref = new int
num_ref[] = 100
ref_test(num_ref)



出力

ref 0x10c40a1c8 --> 300

0x10c40a1c8

ref 0x10c40a1c8 --> 300

ref 0x10c4c8048 --> 100


オブジェクトのポインタの挙動


  • type構文でref型を定義することができる

type

FooObj = object
num: int
Foo = ref FooObj


  • let foo = new Foo などとするとfooはref Foo型になる(new時に確保したメモリの先頭アドレス)


type
FooObj = object
num: int
Foo = ref FooObj

let foo = new Foo

echo repr(foo)

出力

ref 0x106d17048 --> [num = 0]


  • newしたオブジェクトを代入するとシャローコピー(ポインタになってるので当たり前ではある)


type
FooObj = object
num: int
Foo = ref FooObj

let foo = new Foo

echo repr(foo)

let fooPtr = foo

echo repr(fooPtr)

出力

ref 0x10062f048 --> [num = 0]

ref 0x10062f048 --> [num = 0]


  • ref型をptrにしてみる


type
FooObj = object
num: int
Foo = ref FooObj

let foo = new Foo

echo repr(foo)

let fooPtr = foo

echo repr(fooPtr)

let fooPtrR: ptr FooObj = cast[ptr FooObj](new FooObj)

echo repr(fooPtrR)

出力

ref 0x103aca048 --> [num = 0]

ref 0x103aca048 --> [num = 0]

ref 0x103aca060 --> [num = 0]


  • 使うタイミングがあるかは謎