当您使用c()连接R中的两个向量时,它"将参数和结果合并为一个向量".它是通过创建一个新的向量来组合它们,以承担两个向量的元素,还是有一种方法可以真正地组合为这两个向量分配的数据空间?
当我搜索它时,我找不到解释,但c()的可视化表示实际上只是将第二个向量附加到第一个向量的末尾,但我认为这只是为了让我们可以很容易地理解这个函数的作用,而不是实际发生的事情.
我是新来的R,所以任何帮助将不胜感激!
当您使用c()连接R中的两个向量时,它"将参数和结果合并为一个向量".它是通过创建一个新的向量来组合它们,以承担两个向量的元素,还是有一种方法可以真正地组合为这两个向量分配的数据空间?
当我搜索它时,我找不到解释,但c()的可视化表示实际上只是将第二个向量附加到第一个向量的末尾,但我认为这只是为了让我们可以很容易地理解这个函数的作用,而不是实际发生的事情.
我是新来的R,所以任何帮助将不胜感激!
当您调用c()
时,将分配一个new向量,现有向量将合并到其中.在底层C代码中,这种情况会发生here次.
PROTECT(ans = allocVector(mode, data.ans_length));
这看起来可能很浪费,因为我们已经将值写入内存,所以为什么不简单地将指向该内存的几个指针包装起来,并将that称为向量呢?
这有几个原因.
首先,R对向量执行的许多算术和统计操作都是通过迭代连续内存中的元素来完成的.如果元素不是in个连续的内存,这是不可能的.会有很多地址判断步骤,并在内存地址之间跳转,这会使事情变得慢得多.在R之外,出于大致相同的原因,在C或C++中连接向量也是通过分配一个新的向量来完成的.
第二个原因是避免碎片和内存泄漏.如果我们通过连接其他向量的子集来创建一个向量,而不分配专用内存,我们最终会得到一堆指向内存空闲存储中不同位置的指针.如果我们然后使用this个向量的子集,我们将会有一个噩梦:内存指针指向指向向量片段的内存指针,以及垃圾收集器无法重用或回收的未使用的向量片段块.
第三个原因是,R用户期望修改时复制行为.例如,如果我们有:
a <- c(1, 2, 3)
b <- c(a, a)
b
#> [1] 1 2 3 1 2 3
然后,我们希望能够更改单个元素:
b[6] <- 6
b
#> [1] 1 2 3 1 2 6
然而,如果b
没有分配它自己的数据,这个操作将改变b
的第三个元素以及第六个元素.
从概念上讲,R中的内存分配是这样的:每个R对象都存储在C中作为SEXP
对象.这是一个基本上是指向数据本身的指针的 struct ,它作为一个称为SEXPREC
的 struct 存储在内存中.
因此,如果我们运行代码:
A <- 1:4
B <- 5:14
向量A
和B
可以如下存储在存储器中:
如果我们这样做了
C <- c(A, B)
然后在内存中,我们得到:
其中C
指向的SEXPREC中的数据是从A
和B
指向的另外两个SEXPREC对象中的数据复制的