4

在 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;

X我想通过将值插入到它的一个向量中来更新 R 中的一个对象。上面的代码不起作用,所以我尝试了这个:

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>')
4

1 回答 1

12

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

以下是一些流行的答案:

  1. 在 C++ 函数中,如何将 Rcpp 对象传递给其他函数(通过引用或复制)?
  2. 使用 RcppArmadillo submat() 通过引用更新 Rcpp::NumericMatrix
  3. Rcpp 按引用传递与按值传递
  4. 通过引用传递 data.frame 并使用 rcpp 更新它
  5. Rcpp 通过引用传递更新矩阵并返回 R 中的更新
  6. 将大型矩阵传递给 RcppArmadillo 函数而不创建副本(高级构造函数)
  7. Rcpp:与代理模型不一致的行为
  8. 为什么我的 Rcpp 实现查找唯一项目的数量比基本 R 慢?

更多细节...

从 FAQ 条目Rcpp 更改了我通过值传递的 (const) 对象,我写了:

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

所以,这&只是视觉上的糖,因为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

于 2018-01-21T02:51:43.093 回答