Pointers Nim中的价值与参考模型是什么?
注意:我不是在问指针和引用之间的区别,对于这个问题来说,这是完全无关的 有一件事我找不到明确说明——Nim使用什么模型Pointers Nim中的价值与参考模型是什么?,pointers,types,nim-lang,Pointers,Types,Nim Lang,注意:我不是在问指针和引用之间的区别,对于这个问题来说,这是完全无关的 有一件事我找不到明确说明——Nim使用什么模型 类似C++(在这里你有值和新< /Cord> >你创建指向数据的指针(在这种情况下,变量可以保存指针到指向……到数据的指针)?< /P> 或者像C#——您将POD类型作为值,但用户定义的对象带有引用(隐式) 我发现只有去参考是自动的,就像在围棋中一样 重新措辞。你定义了你的新类型,比如说Student(带有姓名、大学、地址)。你写道: var student ...? 使st
类似C++(在这里你有值和<代码>新< /Cord> >你创建指向数据的指针(在这种情况下,变量可以保存指针到指向……到数据的指针)?< /P> 或者像C#——您将POD类型作为值,但用户定义的对象带有引用(隐式)
我发现只有去参考是自动的,就像在围棋中一样 重新措辞。你定义了你的新类型,比如说Student
(带有姓名、大学、地址)。你写道:
var student ...?
student
保存实际数据(属于student
类型/类别)student
保持指向数据的指针ptr
关键字获取不安全指针,主要用于与C代码接口,还有ref
获取垃圾收集的安全参考(两者都记录在Nim手册的章节中)
但是,请注意,即使指定proc
以按值传递变量,编译器也可以自由决定通过引用在内部传递该变量,前提是它认为它可以加快执行速度并且同时是安全的。实际上,我唯一一次使用引用是在我将Nim类型导出到C时,必须确保C和Nim都指向同一个内存。请记住,您始终可以在nimcache
目录中检查生成的C代码。然后您将看到,proc中的var
参数只是指向其C结构的指针
下面是一个类型的示例,该类型的构造函数将在堆栈上创建并通过值传入,以及相应的类似指针的版本:
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
值,您可以将其视为错误,而值构造函数强制您引发异常或更改构造函数以使用下面提到的var表单,以便您可以返回一个表示成功的bool。失败往往以不同的方式处理nil
- 在类C语言中,有一种显式语法来访问指针的内存值或指针指向的内存值(解引用)。在Nim中也有空的下标符号(
)。但是,编译器将尝试自动放置这些内容,以避免代码混乱。因此,本例不使用它们。为了证明这一点,您可以将代码更改为:[]
它将按预期工作和编译。但以下更改将产生编译器错误,因为您无法取消引用非引用类型:echo b[]姓名和$b[]年龄
echo a[].name&''和$a[].age
- Nim社区当前的趋势是区分值和引用类型。在旧的约定中,您将有一个
,参考值的别名为TPerson
。您可以发现许多代码仍然使用此约定PPerson=ref TPerson
- 根据对象和构造函数需要执行的具体操作,除了使用
返回值之外,还可以使用initPerson
。但是隐式init(x:var Person,…)
变量的使用允许编译器对此进行优化,因此它更像是一种味觉偏好或向调用者传递result
的要求bool
- 它可以是
type Student = object ...
大致相当于
typedef struct { ... } Student;
typedef struct { ... } *Student;
在C中,而
type Student = ref object ...
或
大致相当于
typedef struct { ... } Student;
typedef struct { ... } *Student;
在C中(使用
ref
表示垃圾收集器跟踪的引用,而ptr
不跟踪)。对此进行投票的人能否重新表述?我很难理解这个问题。@SimonWhitehead,我更新了这个问题(从更新的答案中,我将提炼出我原始问题的答案:-D)。所以基本上你有C++-比如--var student=student('Joe Doe')
,你有堆栈上的数据,或者var student=new student('Joe Doe'))
并且您有指向堆上分配的数据的指针,对吗?是。我用一种典型的Nimrod方法扩展了答案,即用构造函数过程初始化这两种类型。该示例使用git版本的Nimrod进行了测试,可能无法直接使用上一个稳定的0.9.2版本。+1,非常好,谢谢。为了理解这个模型,我只遗漏了两件事——你能拿一个a
(查看你的代码)指针吗?根据答案——如果您不定义newPerson
,您可以创建对Person
对象的指针/引用吗?您可以通过addr操作符获得指向var的指针(请参阅),但它不像ref那样被垃圾收集。newPerson
过程只是一个方便的过程,没有什么可以阻止您直接编写它的主体,请定义var c:ref Person
并调用new(c)
来分配它。再次感谢您!你提供的链接也解释了很多