4

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>')
user2978524
  • 471
  • 1
  • 3
  • 15
  • 1
    Possible duplicate of [Within C++ functions, how are Rcpp objects passed to other functions (by reference or by copy)?](https://stackoverflow.com/questions/24112893/within-c-functions-how-are-rcpp-objects-passed-to-other-functions-by-referen) – coatless Jan 21 '18 at 03:55

1 Answers1

12

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

enter image description here enter image description here

enter image description here enter image description here

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

Roland
  • 127,288
  • 10
  • 191
  • 288
coatless
  • 20,011
  • 13
  • 69
  • 84
  • 1
    Nice anser and upvoted but ... let's call it a duplicate. – Dirk Eddelbuettel Jan 21 '18 at 03:32
  • 1
    @DirkEddelbuettel https://chat.stackoverflow.com/transcript/message/40899379#40899379 – coatless Jan 21 '18 at 03:55
  • Does this mean if I write `NumericVector X = list_obj_from_R["X"]; X[index] = 5;`, I can insert `5` to the specified index in R object (`X`) without explicitly returning `list_obj_from_R`? – user51966 Jan 22 '18 at 16:22
  • 1
    @user51966 not quite. What happens when you pull an object out from a list is a deep clone. The object has to be reinserted into the list to receive the reference update. – coatless Jan 23 '18 at 05:20