here提到R
在将变量赋给新变量时使用copy-on-modify,包括将参数传递给函数。
然而,切片(vector
,list
,data frame
)是否创建了一个相同类型的新对象,其中包含原始对象子集的oopies,或者是新元素中的元素存储原始对象的副本或仅仅是复制修改参考?
这是一个复杂的话题。你应该先阅读有关NAMED mechanism的内容。
如果运行以下命令,则会看到列表元素没有副本(因为列表基本上是指向其元素的指针):
> a <- list(1, 2, 3, 4, 5)
>
> b <- a[1:2]
> .Internal(inspect(b))
@0x000000001327e5b8 19 VECSXP g0c2 [NAM(3)] (len=2, tl=0)
@0x00000000136f6b60 14 REALSXP g0c1 [NAM(3)] (len=1, tl=0) 1
@0x00000000136f6b28 14 REALSXP g0c1 [NAM(3)] (len=1, tl=0) 2
>
>
> c <- a[1:2]
> .Internal(inspect(c))
@0x000000001327e678 19 VECSXP g0c2 [NAM(3)] (len=2, tl=0)
@0x00000000136f6b60 14 REALSXP g0c1 [NAM(3)] (len=1, tl=0) 1
@0x00000000136f6b28 14 REALSXP g0c1 [NAM(3)] (len=1, tl=0) 2
>
> b[1] <- 6
> .Internal(inspect(b))
@0x000000001327e6f8 19 VECSXP g0c2 [NAM(1)] (len=2, tl=0)
@0x0000000013745b58 14 REALSXP g0c1 [] (len=1, tl=0) 6
@0x00000000136f6b28 14 REALSXP g0c1 [NAM(3)] (len=1, tl=0) 2
>
> .Internal(inspect(c))
@0x000000001327e678 19 VECSXP g0c2 [NAM(3)] (len=2, tl=0)
@0x00000000136f6b60 14 REALSXP g0c1 [NAM(3)] (len=1, tl=0) 1
@0x00000000136f6b28 14 REALSXP g0c1 [NAM(3)] (len=1, tl=0) 2
如果您是子集向量,则会有所不同。
您可能也对new reference counting mechanism感兴趣。
将原子矢量子集设置为较短的原子矢量将为您提供一个新的矢量。从对象中对整个向量进行子集化可以为您提供复制修改引用。这样做的结果是你可以通过子集来获取一个新的更短的列表对象,但它的内容将是对原始内容的引用(没有总体内存成本),直到你修改为止。
有关更多详细信息,请参阅有关内存管理的Hadley's notes。
与python
不同,R
可以在任何时候创建新对象。例如:
> a=c(1,2,3,4,5)
> a
[1] 1 2 3 4 5
> b=a[1]
> b
[1] 1
> b=7
> b
[1] 7
> a
[1] 1 2 3 4 5
对于vectors
,lists
或dataframes
,这同样适用。看看this的R
帖子中的参考对象。