根据我的理解,Nim中的字符串基本上是一个可变的字节序列,并且它们在赋值时被复制。
考虑到这一点,我假设sizeof
会告诉我(如len
)字节数,但它总是在我的64位机器上给出8
,所以看来拿着指针。
鉴于此,我有以下问题......
复制作业背后的动机是什么?是因为它们是可变的吗?
是否有时间分配时不复制? (我假设非var
函数参数不复制。还有其他吗?)
它们是否经过优化,只有当它们发生变异时才真正被复制?
字符串和序列之间是否有任何显着差异,或者上述问题的答案是否同样适用于所有序列?
其他一般值得注意的事情吗?
谢谢!
答案 0 :(得分:10)
字符串的定义实际上在system.nim
中,只是在另一个名称下:
type
TGenericSeq {.compilerproc, pure, inheritable.} = object
len, reserved: int
PGenericSeq {.exportc.} = ptr TGenericSeq
UncheckedCharArray {.unchecked.} = array[0..ArrayDummySize, char]
# len and space without counting the terminating zero:
NimStringDesc {.compilerproc, final.} = object of TGenericSeq
data: UncheckedCharArray
NimString = ptr NimStringDesc
因此,字符串是指向具有len
,reserved
和data
字段的对象的原始指针。字符串的过程在sysstr.nim中定义。
默认情况下,字符串赋值的语义被选择为与Nim中的所有值类型(不是ref或ptr)相同,因此您可以假设赋值创建副本。当一个副本是不必要的时,编译器可以将其删除,但我不确定到目前为止发生了多少。将字符串传递给proc不会复制它们。没有优化可以阻止字符串副本,直到它们发生变异。序列的行为方式相同。
您可以通过将字符串和seq标记为浅层来更改它们的默认赋值行为,然后在赋值时不进行复制:
var s = "foo"
shallow s