Skip to content

Instantly share code, notes, and snippets.

@ggrothendieck
Last active May 5, 2019 17:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ggrothendieck/53811e2769d0582407ae to your computer and use it in GitHub Desktop.
Save ggrothendieck/53811e2769d0582407ae to your computer and use it in GitHub Desktop.
Illustrates that a NumericVector is a pointer
/**
* @title A NumericVector is Really a Pointer
* @author G. Grothendieck completing Michael Meyer's post at https://stat.ethz.ch/pipermail/r-help/2015-August/431645.html
* @license GPL (>= 2)
* @tags NumericVector pointer
* @summary Shows that a NumericVector is a pointer.
*/
// To run: library(Rcpp); sourceCpp("leftShift.cpp")
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector leftShift(NumericVector x){
int n = x.size();
Rprintf("C++: address of x prior to modification <%p>\n", (SEXP)x);
for(int i=0;i<n-1;i++) x[i]=x[i+1];
Rprintf("C++: address of x after modification <%p>\n", (SEXP)x);
return x;
}
// next function is the same except x is a clone of the input
// [[Rcpp::export]]
NumericVector leftShiftClone(NumericVector x0){
NumericVector x(clone(x0));
int n = x.size();
// the address of x0 will be the same as address of x0 in R
// the x addresses will be the same as each other and different from x0
Rprintf("C++: address of x0 <%p>\n", (SEXP)x0);
Rprintf("C++: address of x prior to modification <%p>\n", (SEXP)x);
for(int i=0;i<n-1;i++) x[i]=x[i+1];
Rprintf("C++: address of x after modification <%p>\n", (SEXP)x);
return x;
}
/*** R
library(pryr)
#########################################################
# x, the input, changes
x <- c(1, 2, 3)
address(x) # R: address of x prior to calling C++
y <- leftShift(x)
address(y) # R: address of output y
y
address(x) # R: address of x after calling C++
x # the input, x, has changed!
#########################################################
# x0, the input, is unchanged
x0 <- c(1, 2, 3)
address(x0) # R: address of x0 prior to calling C++
y0 <- leftShiftClone(x0)
address(y0) # R: address of y after calling C++ (same as x in C++)
y0
x0 # since leftShiftClone internally cloned x0 (the input), x0 did not change
address(x0) # R: address of x0 after calling C++ (unchanged)
*/
@ggrothendieck
Copy link
Author

Also note this discussion of swapping without copying in R.
https://stackoverflow.com/questions/54970202/swap-two-sexp-without-copying/54970808#54970808

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment