如何将输入声明为Rcpp函数?

cof*_*nky 5 c++ r rcpp

我是绝对的Rcpp创造者,所以请注意,初学者的问题即将来临.

考虑这个例子:

#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericMatrix mat_1(NumericMatrix X){
 do.stuff.with.X
}
Run Code Online (Sandbox Code Playgroud)

我的理解是,它mat_1在R的工作空间中定义了一个函数,它将数值矩阵作为输入并在最后返回一个数字矩阵.但是,在这里看,我明白我也可以定义

SEXP mat_2(SEXP X){
Rcpp::NumericMatrix x(X);                 
 do.stuff.with.x
}
Run Code Online (Sandbox Code Playgroud)

或者

SEXP mat_3(SEXP X){
NumericMatrix x(as<NumericMatrix>(X))
 do.stuff.with.x
}
Run Code Online (Sandbox Code Playgroud)

我的理解是,它将函数的输出定义为S表达式,并且它需要一个S表达式作为输入,它在内部转换(?)为数字矩阵.

现在,看看这份对我来说非常宝贵资源的文件,我知道我也可以写作

NumericMatrix mat_4( NumericMatrix X&){
 do.stuff.with.X
}
Run Code Online (Sandbox Code Playgroud)

在这里,我的理解是,而不是使副本X,在Rcpp-函数使用到的参考 R对象.我其实不确定我明白这意味着什么.是不是没有使用SEXP副本,或者我做错了什么?此外,如果它节省了内存并因此更有效,为什么我会使用其他东西?

我相信我错过了一些选择.无论如何,我的一个大问题是:R用户(我)的角度来看,我调用每个函数mat_1, mat_2, mat_3mat_4提供一个数字矩阵(在我的工作区中是一个R对象,因而是一个SEXP),看来我应该得到相同的输出(一个数字矩阵,SEXP无论如何都是这样R,对吗?).对于这些看似相同的定义函数的方法的相对优点,我将不胜感激.也就是说,假设我们确切知道函数输入将是什么以及输出将是什么,

  1. 为什么以及何时使用NumericMatrix而不是SEXP用于论证,反之亦然?
  2. 为什么以及何时使用&
  3. 如果我知道该函数将返回一个数字矩阵,是否有理由将该函数声明为SEXP?有理由坚持下去NumericMatrix吗?

还是我完全忽略了这一点?

此外,在mat_2和中使用的转换之间是否有任何实际差异mat_3?也就是说,Rcpp::NumericMatrix x(X)和之间是否存在差异NumericMatrix x(as<NumericMatrix>(X))

任何反馈都表示赞赏.

Rom*_*ois 5

好的.试图给出一些线索.首先,如果你是初学者,你使用第一个函数就可以了mat_1.随着你的技能提高,你可能会理解它们之间的一些差异mat_1,并最终转向......使用mat_1,因为那是你想要使用的.

  1. 总是.大多数用户不应该使用SEXP.
  2. 在这种情况下它没有任何区别.Rcpp将知道如何处理引用,但发生的情况几乎相同,它会在某处创建一个对象,并为您提供引用.如果你mat_4要从另一个C++函数调用,那么传递值和引用之间的区别会有所不同.
  3. 如果您知道类型,请使用类型.这就是Rcpp的全部观点.SEXP是R的捕获所有类型,如果你返回SEXP它可以是任何东西,如果你返回一个NumericMatrix你知道的设计,你返回一个数字矩阵,巨大的优势和几乎Rcpp存在的全部原因.

我让你决定你是否错过了这一点.

通常情况下as<>会更加努力,但在这种情况下并没有什么不同.

简而言之:使用mat_1.还有很多其他的东西要学习,不要关心这个.

  • 在SEXP之外的NumericMatrix中没有额外的内存,没有,零.不管矩阵有多大.您不需要支付NumericMatrix.然而,您可以使用方便的东西.对于2,不是真的,通过值传递矩阵是便宜的,因为数据不会被复制,只有指针.鉴于代码示例`do.stuff.with.X`,我不能说更多.对于像NumericMatrix这样的Rcpp类型,只需按值传递它们. (2认同)