在R中,是否不应该使用单一名称绑定修改对象以保留其内存地址?

时间:2019-05-12 21:06:27

标签: r

后期编辑:重要说明:此处报告的行为似乎仅在RStudio中发生,而不是在R终端中发生。

我的RStudio版本是:1.2.1511。

我试图了解R中的对象何时发生适当的位置更改,或者何时遵循copy-on-modify语义。

Hadley's Advanced R book为例。

在该示例中,Hadley演示了如何在R中修改对象。他谈到了两种情况:具有单一名称绑定的对象和环境。

我尝试了使用向量v的示例,但更改了其中一个值后,向量v的地址没有得到保留。

在向量3的位置3上改变值v之后,v的存储地址从0x5583a1461fb8变为0x5583a2c5f608

所以我的问题是为什么?这似乎与哈德利的书本范例相矛盾。

v <- c(1, 2, 3)
pryr::address(v)
#> [1] "0x5583a1461fb8"
lobstr::obj_addr(v)
#> [1] "0x5583a1461fb8"
v[[3]] <- 4
pryr::address(v)
#> [1] "0x5583a2c5f608"
lobstr::obj_addr(v)
#> [1] "0x5583a2c5f608"
sessionInfo()
#> R version 3.5.1 (2018-07-02)
#> Platform: x86_64-pc-linux-gnu (64-bit)
#> Running under: Arch Linux
#> 
#> Matrix products: default
#> BLAS: /usr/lib/libblas.so.3.8.0
#> LAPACK: /usr/lib/liblapack.so.3.8.0
#> 
#> locale:
#>  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
#>  [3] LC_TIME=en_DK.utf8         LC_COLLATE=en_US.UTF-8    
#>  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
#>  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
#>  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> loaded via a namespace (and not attached):
#>  [1] Rcpp_1.0.1       codetools_0.2-15 digest_0.6.18    rprojroot_1.3-2 
#>  [5] backports_1.1.2  magrittr_1.5     evaluate_0.12    rlang_0.3.4     
#>  [9] stringi_1.4.3    pryr_0.1.4       rmarkdown_1.10   lobstr_1.0.1    
#> [13] tools_3.5.1      stringr_1.4.0    yaml_2.2.0       compiler_3.5.1  
#> [17] htmltools_0.3.6  knitr_1.20

P.S。我使用了pryrlobstr包来查找内存地址。我也尝试使用tracemem(),但出现此错误:

 Error in tracemem(m) : 
  R was not compiled with support for memory profiling

1 个答案:

答案 0 :(得分:2)

如另一个问题所述:

In place modification of matrices in R

问题在于RStudio的“环境”窗格引用了v。因此v向量不再是单个名称bound(?)...因此,当我们更改v时,R需要复制它。

fn <- function() {
  v <- c(1, 2, 3)
  print(pryr::address(v))
  print(lobstr::obj_addr(v))
  v[[3]] <- 4
  print(pryr::address(v))
  print(lobstr::obj_addr(v))
}

fn()
#> [1] "0x55e4acd1b538"
#> [1] "0x55e4acd1b538"
#> [1] "0x55e4acd1b538"
#> [1] "0x55e4acd1b538"