There is no deep copy in Rcpp unless you request it with clone . When you pass in the value, you create a new List object, but it uses the same base object R.
Thus, there are different values ββbetween passing by value and passing by reference.
However, when you pass by value, you have to pay the price for protecting the main object again. This may incur an extra charge, since this Rcpp relies on a recursive, not very efficient R_PreserveObject .
My guide will follow the link whenever possible so that you do not pay extra protection. If you know that ABCfun2 will not change the object, I would advise you to pass a link to const: ABCfun2( const List& ) . If you are going to make changes to the List , I would recommend using ABCfun2( List& ) .
Consider this code:
#include <Rcpp.h> using namespace Rcpp ; #define DBG(MSG,X) Rprintf("%20s SEXP=<%p>. List=%p\n", MSG, (SEXP)X, &X ) ; void fun_copy( List x, const char* idx ){ x[idx] = "foo" ; DBG( "in fun_copy: ", x) ; } void fun_ref( List& x, const char* idx ){ x[idx] = "bar" ; DBG( "in fun_ref: ", x) ; } // [[Rcpp::export]] void test_copy(){ // create a list of 3 components List data = List::create( _["a"] = 1, _["b"] = 2 ) ; DBG( "initial: ", data) ; fun_copy( data, "a") ; DBG( "\nafter fun_copy (1): ", data) ; // alter the 1st component of ths list, passed by value fun_copy( data, "d") ; DBG( "\nafter fun_copy (2): ", data) ; } // [[Rcpp::export]] void test_ref(){ // create a list of 3 components List data = List::create( _["a"] = 1, _["b"] = 2 ) ; DBG( "initial: ", data) ; fun_ref( data, "a") ; DBG( "\nafter fun_ref (1): ", data) ; // alter the 1st component of ths list, passed by value fun_ref( data, "d") ; DBG( "\nafter fun_ref (2): ", data) ; }
All I do is pass a list of the function, update it and print some information about the pointer to the main R object and the pointer to the List ( this ) object.
Here are the results of what happens when I call test_copy and test_ref :
> test_copy() initial: SEXP=<0x7ff97c26c278>. List=0x7fff5b909fd0 in fun_copy: SEXP=<0x7ff97c26c278>. List=0x7fff5b909f30 after fun_copy (1): SEXP=<0x7ff97c26c278>. List=0x7fff5b909fd0 $a [1] "foo" $b [1] 2 in fun_copy: SEXP=<0x7ff97b2b3ed8>. List=0x7fff5b909f20 after fun_copy (2): SEXP=<0x7ff97c26c278>. List=0x7fff5b909fd0 $a [1] "foo" $b [1] 2
Let's start with the existing list associated with object R.
initial: SEXP=<0x7fda4926d278>. List=0x7fff5bb5efd0
We pass it by the value of fun_copy , so we get a new List , but using the same basic R object:
in fun_copy: SEXP=<0x7fda4926d278>. List=0x7fff5bb5ef30
Exit fun_copy . the same main R object back and forth to the original List :
after fun_copy (1): SEXP=<0x7fda4926d278>. List=0x7fff5bb5efd0
Now we call fun_copy again, but this time we are updating a component that was not in the list: x["d"]="foo" .
in fun_copy: SEXP=<0x7fda48989120>. List=0x7fff5bb5ef20
List had no choice but to create a new basic R object, but this object lies only in the local List . Therefore, when we exit get_copy , we return to the original List with its original SEXP subtext.
after fun_copy (2): SEXP=<0x7fda4926d278>. List=0x7fff5bb5efd0
The main thing is that the first time "a" already on the list, so we updated the data directly. Since the local fun_copy object and the external object from test_copy have the same base object R, modifications were common inside fun_copy .
The second time, fun_copy grows its local List object, associating it with a new SEXP that does not extend to an external function.
Now consider what happens when you follow the link:
> test_ref() initial: SEXP=<0x7ff97c0e0f80>. List=0x7fff5b909fd0 in fun_ref: SEXP=<0x7ff97c0e0f80>. List=0x7fff5b909fd0 after fun_ref(1): SEXP=<0x7ff97c0e0f80>. List=0x7fff5b909fd0 $a [1] "bar" $b [1] 2 in fun_ref: SEXP=<0x7ff97b5254c8>. List=0x7fff5b909fd0 after fun_ref(2): SEXP=<0x7ff97b5254c8>. List=0x7fff5b909fd0 $a [1] "bar" $b [1] 2 $d [1] "bar"
There is only one List object 0x7fff5b909fd0 . When we need to get the new SEXP in the second call, it will correctly extend to the external level.
For me, the behavior that you get when passing through links is much easier to reason about.