【问题标题】:Declare a variable as a reference in Rcpp在 Rcpp 中声明一个变量作为引用
【发布时间】:2018-06-29 23:48:15
【问题描述】:

在 C++ 中,我们可以将变量声明为引用。

int a = 10;
int& b = a;

如果我们设置b=15,a 也会改变。

我想在 Rcpp 中做类似的事情。

List X = obj_from_R["X"];
IntegerVector x_i = X[index];
x_i = value;

我想从 R 中更新一个名为 X 的对象,方法是在其向量之一中插入一个值。上面的代码不起作用,所以我尝试了这个:

IntegerVector& x_i = X[index];

并收到一个错误。

error: non-const lvalue reference to type 'IntegerVector'
      (aka 'Vector<13>') cannot bind to a temporary of type 'Proxy' (aka 'generic_proxy<19>')

【问题讨论】:

标签: rcpp rcpp11


【解决方案1】:

这个问题被问了很多不同的变体。

以下是一些流行的答案:

  1. Within C++ functions, how are Rcpp objects passed to other functions (by reference or by copy)?
  2. Update Rcpp::NumericMatrix passed by reference using RcppArmadillo submat()
  3. Rcpp pass by reference vs. by value
  4. Passing by reference a data.frame and updating it with rcpp
  5. Rcpp Update matrix passed by reference and return the update in R
  6. Passing large matrices to RcppArmadillo function without creating copy (advanced constructors)
  7. Rcpp: Inconsistent behavior with proxy model
  8. Why is my Rcpp implementation for finding the number of unique items slower than base R?

更多细节...

来自我写的常见问题解答条目 Rcpp changed the (const) object I passed by value:

Rcpp 对象是底层 R 对象的 SEXP 或 S 表达式的包装器。 SEXP 是一个指针变量,它保存 R 对象数据的存储位置R:Internals。也就是说,SEXP 不保存 R 对象的实际数据,而只是对数据所在位置的引用。当为 R 对象创建新的 Rcpp 对象以进入 C++ 时,该对象将使用与原始 R 相同的 SEXP 对象,如果类型匹配,否则必须创建一个新的 SEXP 以保证类型安全。本质上,底层的 SEXP 对象是通过引用传递的,而没有显式复制到 C++ 中。我们将这种安排称为代理模型。

所以,&amp; 只是视觉上的糖,因为 Rcpp 对象已经充当了引用。

因此,以下将显示结论:

#include <Rcpp.h>

// [[Rcpp::export]]
void show_references(Rcpp::List X, 
                     Rcpp::IntegerVector y, 
                     int index = 0) {
  X[index] = y;
}

例子:

y_vec = c(-1L, 8L, 12L)
X_list = list(a = c(0L, 2L, 3L), b = c(42L, 50L, 30L))
X_list
# $a
# [1] 0 2 3
#
# $b
# [1] 42 50 30

show_references(X_list, y_vec)
X_list
# $a
# [1] -1  8 12
#
# $b
# [1] 42 50 30

我创建的以下 Rcpp 代理模型幻灯片应该进一步说明正在发生的事情

来源:https://twitter.com/axiomsofxyz/status/938881541396197377

【讨论】:

  • 不错的分析器和赞成但......让我们称之为重复。
  • 这是否意味着如果我写NumericVector X = list_obj_from_R["X"]; X[index] = 5;,我可以将5插入R对象(X)中的指定索引而不显式返回list_obj_from_R?
  • @user51966 不完全是。当您从列表中拉出一个对象时会发生什么是深度克隆。必须将对象重新插入到列表中才能接收引用更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-29
  • 1970-01-01
  • 2015-03-17
  • 1970-01-01
  • 2010-10-30
  • 2020-06-14
相关资源
最近更新 更多