jfiedler
jfiedler

Reputation: 43

Rcpp and R: pass by reference

Working with Rcpp and R I observed the following behaviour, which I do not understand at the moment. Consider the following simple function written in Rcpp

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
NumericMatrix hadamard_product(NumericMatrix & X, NumericMatrix & Y){
   unsigned int ncol = X.ncol();
   unsigned int nrow = X.nrow();
   int counter = 0;
   for (unsigned int j=0; j<ncol; j++) {
     for (unsigned int i=0; i<nrow; i++)  {
        X[counter++] *= Y(i, j);
     }
   }
   return X;
}

This simply returns the component-wise product of two matrices. Now I know that the arguments to this function are passed by reference, i.e., calling

M <- matrix(rnorm(4), ncol = 2)
N <- matrix(rnorm(4), ncol = 2)
M_copy <- M
hadamard_product(M, N)

will overwrite the original M. However, it also overwrites M_copy, which I do not understand. I thought that M_copy <- M makes a copy of the object M and saves it somewhere in the memory and not that this assignment points M_copy to M, which would be the behaviour when executing

x <- 1
y <- x
x <- 2

for example. This does not change y but only x.

So why does the behaviour above occur?

Upvotes: 2

Views: 785

Answers (1)

Roland
Roland

Reputation: 132864

No, R does not make a copy immediately, only if it is necessary, i.e., copy-on-modify:

x <- 1
tracemem(x)
#[1] "<0000000009A57D78>"
y <- x
tracemem(x)
#[1] "<0000000009A57D78>"
x <- 2
tracemem(x)
#[1] "<00000000099E9900>"

Since you modify M by reference outside R, R can't know that a copy is necessary. If you want to ensure a copy is made, you can use data.table::copy. Or avoid the side effect in your C++ code, e.g., make a deep copy there (by using clone).

Upvotes: 5

Related Questions