Ответ 1
Они являются "прокси-моделью" - ваш xa
действительно является тем же самым местом памяти, что и ваш исходный объект, поэтому вы в конечном итоге меняете свой оригинал.
Если вы этого не хотите, вы должны сделать одно: (глубокую) копию с использованием метода clone()
или, возможно, явное создание нового объекта, в который будет записан измененный объект. Второй метод этого не делает, вы просто используете две разные именованные переменные, которые являются "указателями" (в смысле прокси-модели) исходной переменной.
Однако дополнительное осложнение заключается в неявной передаче и копировании, когда вы передаете вектор int (от R) до типа NumericVector: он создает копию, а затем оригинал больше не изменяется.
Вот более явный пример, аналогичный тому, который я использую в учебниках или семинарах:
library(inline)
f1 <- cxxfunction(signature(a="numeric"), plugin="Rcpp", body='
Rcpp::NumericVector xa(a);
int n = xa.size();
for(int i=0; i < n; i++) {
if(xa[i]<0) xa[i] = 0;
}
return xa;
')
f2 <- cxxfunction(signature(a="numeric"), plugin="Rcpp", body='
Rcpp::NumericVector xa(a);
int n = xa.size();
Rcpp::NumericVector xr(a); // still points to a
for(int i=0; i < n; i++) {
if(xr[i]<0) xr[i] = 0;
}
return xr;
')
p <- seq(-2,2)
print(class(p))
print(cbind(f1(p), p))
print(cbind(f2(p), p))
p <- as.numeric(seq(-2,2))
print(class(p))
print(cbind(f1(p), p))
print(cbind(f2(p), p))
и вот что я вижу:
[email protected]:~/svn/rcpp/pkg$ r /tmp/ari.r
Loading required package: methods
[1] "integer"
p
[1,] 0 -2
[2,] 0 -1
[3,] 0 0
[4,] 1 1
[5,] 2 2
p
[1,] 0 -2
[2,] 0 -1
[3,] 0 0
[4,] 1 1
[5,] 2 2
[1] "numeric"
p
[1,] 0 0
[2,] 0 0
[3,] 0 0
[4,] 1 1
[5,] 2 2
p
[1,] 0 0
[2,] 0 0
[3,] 0 0
[4,] 1 1
[5,] 2 2
[email protected]:~/svn/rcpp/pkg$
Так что действительно важно, передаете ли вы int-to-float или float-to-float.