Nimrod的价值与参考模型是什么?

gre*_*man 21 types pointers nim-lang

注意:我不是在询问指针和引用之间的区别,对于这个问题,它完全无关紧要.

有一点我无法明确说明 - 尼姆罗德使用的是什么型号?

就像C++一样 - 你有值并且new你创建了指向数据的指针(在这种情况下,变量可以保存指向指向数据的指针的指针)?

或者像C# - 你有POD类型作为值,但用户定义的对象有引用(隐式)?

我发现只有dereferencing是自动的,就像在Go中一样.

另一种方式.你定义你的新类型,比方说Student(名字,大学,地址).你写:

var student ...?
Run Code Online (Sandbox Code Playgroud)
  1. 使student保持实际数据(的Student类型/类)
  2. 使student持有的指针数据
  3. 使student持有指针的指针数据

或者那些点不可能?

Grz*_*icz 28

默认情况下,模型是按值传递数据.当您创建特定类型的var时,编译器将在堆栈上为变量分配所需的空间.这是预期的,因为Nim编译为C,复杂类型只是结构.但是就像在C或C++中一样,你也可以有指针.还有就是ptr得到一个不安全的指针,大多用于连接C代码关键字,并有一个ref以得到垃圾收集安全引用(在两个记录参考文献和指针类型稔手册的部分).

但是,请注意,即使指定a proc按值传递变量,编译器也可以自由决定在内部通过引用传递它,如果它认为它可以加快执行速度并且同时是安全的.在实践中,我唯一使用引用的时候是我 Nim类型导出到C并且必须确保C和Nim都指向相同的内存.请记住,您始终可以检查nimcache目录中生成的C代码.然后,您将看到varproc 中的参数只是指向其C结构的指针.

下面是一个类型的示例,其中构造函数将在堆栈上创建并通过值传入,并且相应的指针类似于version:

type
  Person = object
    age: int
    name: string

proc initPerson(age: int, name: string): Person =
  result.age = age
  result.name = name

proc newPerson(age: int, name: string): ref Person =
  new(result)
  result.age = age
  result.name = name

when isMainModule:
  var
    a = initPerson(3, "foo")
    b = newPerson(4, "bar")

  echo a.name & " " & $a.age
  echo b.name & " " & $b.age
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,代码基本相同,但存在一些差异:

  • 区分初始化的典型方法是将init用于值类型,将new用于引用类型.另外,还要注意稔自己的标准库的错误本公约,因为一些代码早于它(如newStringOfCap并没有返回一个字符串类型的引用).
  • 根据构造函数实际执行的操作,ref版本允许您返回一个nil值,您可以将其视为错误,而值构造函数会强制您引发异常或更改构造函数以使用下面提到的var形式,以便您可以返回bool表示成功.失败倾向于以不同的方式对待.
  • 在类C语言中,theres是一种显式语法,用于访问指针的内存值或其指向的内存值(解除引用).在Nim中也有,它是空的下标符号([]).但是,编译器将尝试自动放置这些以避免混乱代码.因此,该示例不使用它们.要证明这一点,您可以将代码更改为:

    echo b[].name & " " & $b[].age

    哪个将按预期工作和编译.但是,以下更改将产生编译器错误,因为您无法取消引用非引用类型:

    echo a[].name & " " & $a[].age

  • Nim社区目前的趋势是摆脱单字母前缀来区分价值与参考类型.在约定中,您将获得TPerson参考值的a 和别名as PPerson = ref TPerson.您仍然可以使用此约定找到许多代码.

  • 根据你的对象和构造函数究竟需要做什么,而不是initPerson返回值,你也可以有一个init(x: var Person, ...).但隐式result变量的使用允许编译器对此进行优化,因此更多的是品味偏好或bool将调用传递给调用者的要求.

  • 是.我用典型的Nimrod方法扩展了答案,用构造函数procs初始化这两种类型.该示例使用gim版本的Nimrod进行测试,可能无法直接使用最后一个稳定的0.9.2版本. (2认同)

Rei*_*nds 5

它可以是.

type Student = object ...
Run Code Online (Sandbox Code Playgroud)

大致相当于

typedef struct { ... } Student;
Run Code Online (Sandbox Code Playgroud)

在C,同时

type Student = ref object ...
Run Code Online (Sandbox Code Playgroud)

要么

type Student = ptr object ...
Run Code Online (Sandbox Code Playgroud)

大致相当于

typedef struct { ... } *Student;
Run Code Online (Sandbox Code Playgroud)

在C中(ref表示由垃圾收集器跟踪的引用,ptr而不跟踪).