-->

Declare a variable as a reference in Rcpp

2019-01-26 00:47发布

问题:

In C++, we can declare a variable as a reference.

int a = 10;
int& b = a;

If we set b=15, a also changes.

I want to do the similar thing in Rcpp.

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

I want to update an object from R called X by inserting a value to one of its vector. The code above did not work, so I tried this:

IntegerVector& x_i = X[index];

and received an error.

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

回答1:

This question gets asked a lot in differing variants.

Here are some popular answers:

  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?

More details...

From the FAQ entry Rcpp changed the (const) object I passed by value that I wrote:

Rcpp objects are wrappers around the underlying R objects' SEXP, or S-expression. The SEXP is a pointer variable that holds the location of where the R object data has been stored R:Internals. That is to say, the SEXP does not hold the actual data of the R object but merely a reference to where the data resides. When creating a new Rcpp object for an R object to enter C++, this object will use the same SEXP that powers the original R object if the types match otherwise a new SEXP must be created to be type safe. In essence, the underlying SEXP objects are passed by reference without explicit copies being made into C++. We refer to this arrangement as a proxy model.

So, the & is just visual sugar as Rcpp objects already act as references.

Thus, the following would show the conclusion:

#include <Rcpp.h>

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

Example:

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

The following Rcpp proxy model slides I created should further illustrate what is happening

Source: https://twitter.com/axiomsofxyz/status/938881541396197377



标签: rcpp rcpp11