注意:我不是在询问指针和引用之间的区别,对于这个问题,这完全是无关紧要的。
我无法明确指出的一件事 - 尼姆罗德使用的是什么型号?
与C ++一样 - 你有值和new
你创建数据指针(在这种情况下,变量可以保存指向指向数据的指针的指针)?
或者像C# - 你有POD类型作为值,但用户定义的对象有引用(隐式)?
我发现只有解除引用才是自动的,就像Go。
一样改写。您可以定义新类型,例如Student
(包括姓名,大学,地址)。你写道:
var student ...?
student
保存实际数据(Student
类型/类别)student
保持指向数据的指针student
保持指向数据指针的指针或者那些点不可能?
答案 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
正如您所看到的,代码基本相同,但存在一些差异:
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
。)