RCPP通过引用与按值传递

我通过第一次对Rcpp函数进行了测试inline,它解决了我的速度问题(感谢Dirk!): R:将负值替换为零


初始版本如下所示:


library(inline)

cpp_if_src <- '

  Rcpp::NumericVector xa(a);

  int n_xa = xa.size();

  for(int i=0; i < n_xa; i++) {

    if(xa[i]<0) xa[i] = 0;

  }

  return xa;

'

cpp_if <- cxxfunction(signature(a="numeric"), cpp_if_src, plugin="Rcpp")

但是,当调用时cpp_if(p),它会覆盖p输出,这与预期不符。因此,我认为它是通过引用传递的。


所以我用以下版本修复了它:


library(inline)

cpp_if_src <- '

  Rcpp::NumericVector xa(a);

  int n_xa = xa.size();

  Rcpp::NumericVector xr(a);

  for(int i=0; i < n_xa; i++) {

    if(xr[i]<0) xr[i] = 0;

  }

  return xr;

'

cpp_if <- cxxfunction(signature(a="numeric"), cpp_if_src, plugin="Rcpp")

这似乎工作。但是现在当我将其重新加载到R中时,原始版本不再覆盖其输入(即,相同的精确代码现在也不会覆盖其输入):


> cpp_if_src <- '

+   Rcpp::NumericVector xa(a);

+   int n_xa = xa.size();

+   for(int i=0; i < n_xa; i++) {

+     if(xa[i]<0) xa[i] = 0;

+   }

+   return xa;

+ '

> cpp_if <- cxxfunction(signature(a="numeric"), cpp_if_src, plugin="Rcpp")

> p

 [1] -5 -4 -3 -2 -1  0  1  2  3  4  5

> cpp_if(p)

 [1] 0 0 0 0 0 0 1 2 3 4 5

> p

 [1] -5 -4 -3 -2 -1  0  1  2  3  4  5

我不是唯一尝试复制此行为并发现不一致结果的人:


http://chat.stackoverflow.com/transcript/message/4357344#4357344


这里发生了什么?


海绵宝宝撒
浏览 550回答 2
2回答

慕莱坞森

它们的关键是“代理模型”-您xa的存储位置确实与原始对象相同,因此最终需要更改原始对象。如果您不希望这样做,则应该做一件事:使用该clone()方法进行(深度)复制,或者显式创建一个新对象,将更改后的对象写入该对象。方法二不能做到这一点,您只需使用两个名称不同的变量,它们都是原始变量的“指针”(就代理模型而言)。但是,当您将int向量(从R)传递给NumericVector类型时,隐式转换和复制会带来另外的复杂性:创建一个副本,然后不再更改原始副本。这是一个更明确的示例,类似于我在教程或研讨会中使用的示例:library(inline)f1 <- cxxfunction(signature(a="numeric"), plugin="Rcpp", body='&nbsp; Rcpp::NumericVector xa(a);&nbsp; int n = xa.size();&nbsp; for(int i=0; i < n; i++) {&nbsp; &nbsp; if(xa[i]<0) xa[i] = 0;&nbsp; }&nbsp; return xa;')f2 <- cxxfunction(signature(a="numeric"), plugin="Rcpp", body='&nbsp; Rcpp::NumericVector xa(a);&nbsp; int n = xa.size();&nbsp; Rcpp::NumericVector xr(a);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // still points to a&nbsp; for(int i=0; i < n; i++) {&nbsp; &nbsp; if(xr[i]<0) xr[i] = 0;&nbsp; }&nbsp; return xr;')p <- seq(-2,2)print(class(p))print(cbind(f1(p), p))print(cbind(f2(p), p))p <- as.numeric(seq(-2,2))print(class(p))print(cbind(f1(p), p))print(cbind(f2(p), p))这就是我所看到的:edd@max:~/svn/rcpp/pkg$ r /tmp/ari.rLoading required package: methods[1] "integer"&nbsp; &nbsp; &nbsp; &nbsp; p[1,] 0 -2[2,] 0 -1[3,] 0&nbsp; 0[4,] 1&nbsp; 1[5,] 2&nbsp; 2&nbsp; &nbsp; &nbsp; &nbsp; p[1,] 0 -2[2,] 0 -1[3,] 0&nbsp; 0[4,] 1&nbsp; 1[5,] 2&nbsp; 2[1] "numeric"&nbsp; &nbsp; &nbsp; &nbsp;p[1,] 0 0[2,] 0 0[3,] 0 0[4,] 1 1[5,] 2 2&nbsp; &nbsp; &nbsp; &nbsp;p[1,] 0 0[2,] 0 0[3,] 0 0[4,] 1 1[5,] 2 2edd@max:~/svn/rcpp/pkg$因此,无论是从int到float还是从float到float都是非常重要的。

浮云间

这很有趣。知道这一点的唯一方法是通过我猜想的调试器(或者您像Dirk一样编写程序包)。有没有办法将调试器附加到Rcpp函数?我正在考虑像Visual Studio调试器那样附加dll的方法,然后单击该dll即可进入代码。
打开App,查看更多内容
随时随地看视频慕课网APP