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

时间:2014-02-28 13:45:37

标签: pointers types nimrod nim

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

我无法明确指出的一件事 - 尼姆罗德使用的是什么型号?

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

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

我发现只有解除引用才是自动的,就像Go。

一样

改写。您可以定义新类型,例如Student(包括姓名,大学,地址)。你写道:

var student ...?
  1. 使student保存实际数据(Student类型/类别)
  2. 使student保持指向数据的指针
  3. 使student保持指向数据指针的指针
  4. 或者那些点不可能?

2 个答案:

答案 0 :(得分:28)

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

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

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

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

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

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

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

  • Nim社区目前的趋势是get rid of single letter prefixes区分价值与参考类型。在约定中,您将获得TPerson和参考值的别名PPerson = ref TPerson。您仍然可以使用此约定找到许多代码。

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

答案 1 :(得分:5)

它可以是。

type Student = object ...

大致相当于

typedef struct { ... } Student;
在C中

,而

type Student = ref object ...

type Student = ptr object ...

大致相当于

typedef struct { ... } *Student;
C中的

ref表示垃圾收集器跟踪的引用,而不跟踪ptr。)