【发布时间】:2022-10-05 05:46:18
【问题描述】:
我的印象是序列和字符串总是在赋值时被深度复制。今天,当我与一个 C 库交互时,我被烧毁了,我将 Nim 序列的 unsafeAddr 传递给该库。 C 库从传递的指针开始写入内存区域。
由于我不希望库更改原始 Nim 序列,因此我想通过将序列分配给名为 copy 的新变量来简单地复制序列,并将副本的地址传递给库。
瞧,这些修改仍然出现在最初的 Nim 序列中。更奇怪的是,这种行为取决于副本是通过let copy = ...(确实显示更改)还是通过var copy = ...(更改不显示)声明的。
以下代码在一个非常简化的 Nim 示例中演示了这一点:
proc changeArgDespiteCopyAssignment(x: seq[int], val: int): seq[int] =
let copy = x
let copyPtr = unsafeAddr(copy[0])
copyPtr[] = val
result = copy
proc dontChangeArgWhenCopyIsDeclaredAsVar(x: seq[int], val: int): seq[int] =
var copy = x
let copyPtr = unsafeAddr(copy[0])
copyPtr[] = val
result = copy
let originalSeq = @[1, 2, 3]
var ret = changeArgDespiteCopyAssignment(originalSeq, 9999)
echo originalSeq
echo ret
ret = dontChangeArgWhenCopyIsDeclaredAsVar(originalSeq, 7777)
echo originalSeq
echo ret
这打印
@[9999, 2, 3]
@[9999, 2, 3]
@[9999, 2, 3]
@[7777, 2, 3]
所以第一个电话改变了
originalSeq,而第二个电话没有。有人可以解释引擎盖下发生了什么吗? 我正在使用 Nim 1.6.6 和一个 Nim 新手。
【问题讨论】:
标签: sequence deep-copy nim-lang copy-assignment