我似乎已经生成了一些代码,即使使用:=
,data.table实际上也会在赋值时进行复制。以下是一个玩具示例,说明了这一点。 copy.A()
接受参数DT(通过引用传递的data.table)和整数n。它打印DT的地址,将A复制到新列,然后打印DT的新地址。什么都没有归还; copy.A()
旨在通过副作用进行操作。
DT <- data.table(A=rnorm(10000))
copy.A <- function(DT, n) {
address.start <- address(DT)
DT[, sprintf('A.copy.%i', n):=A]
address.final <- address(DT)
cat(sprintf('%.3i) %s --> %s\n', n, address.start, address.final))
}
for(n in 1L:120L)
copy.A(DT, n)
输出:
001) 0x2d979d0 --> 0x2d979d0
002) 0x2d979d0 --> 0x2d979d0
...
098) 0x2d979d0 --> 0x2d979d0
099) 0x2d979d0 --> 0x2d979d0
100) 0x2d979d0 --> 0x6564820 # Copying starts to occur
101) 0x2d979d0 --> 0x2bcfa30
102) 0x2d979d0 --> 0x456cad0
103) 0x2d979d0 --> 0x4282570
...
在某些时候,地址在分配发生时开始改变。基于这个例子,我会说每当我们修改一个通过引用作为参数传递的data.table时,我们必须显式地返回data.table,否则无法保证更改将持续存在。我应该补充一点,这种行为并不令人惊讶。我还没有意识到它一直在发生。
这个问题实际上只是要求提供更多信息。我还没有在文档中找到真正讨论它的任何内容。有人能否对这种引擎盖下的复制行为有所了解,或者可能指出一些解释这一点的文档? data.table是否总是预先分配相同数量的内存,并且随着data.table的大小增加,内存分配的规则是什么?