The difference between values ​​and reference arguments in Rcpp

Consider these two functions:

library(Rcpp)

cppFunction("NumericVector func1(NumericVector &x)
{
    for (int i = 0; i < x.length(); i++)
        x[i] = x[i] * 2;
    return x;
}")


cppFunction("NumericVector func2(NumericVector x)  // no &
{
    for (int i = 0; i < x.length(); i++)
        x[i] = x[i] * 2;
    return x;
}")

The only difference is that it func1takes xas a reference parameter, while it func2takes it as a value. If it were regular C ++, I would understand this, since it is func1allowed to change the value xin the calling code, whereas this will not happen in func2.

However:

> x <- 1:10/5  # ensure x is numeric, not integer
> x
 [1] 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0
> func1(x)
 [1] 0.4 0.8 1.2 1.6 2.0 2.4 2.8 3.2 3.6 4.0
> x
 [1] 0.4 0.8 1.2 1.6 2.0 2.4 2.8 3.2 3.6 4.0  # x in calling env has been modified


> x <- 1:10/5  # reset x
> x
 [1] 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0
> func2(x)
 [1] 0.4 0.8 1.2 1.6 2.0 2.4 2.8 3.2 3.6 4.0
> x
 [1] 0.4 0.8 1.2 1.6 2.0 2.4 2.8 3.2 3.6 4.0  # x is also modified

So, it looks like func1and func2behave the same way, as far as it concerns the adverse effects for the arguments.

What is the reason for this? In general, is it better to pass arguments to Rcpp functions by reference or by value?

+4
source share
1 answer

-, NumericVector, - . , , NumericVector.

cppFunction("void func1(NumericVector& x)
            {
            for (int i = 0; i < x.length(); i++)
            x[i] = x[i] * 2;
            }")


cppFunction("void func2(NumericVector x)  // no &
            {
            for (int i = 0; i < x.length(); i++)
            x[i] = x[i] * 2;
            }")

x <- 1:10/5
func1(x)
print(x)

x <- 1:10/5
func2(x)
print(x)

-, a NumericVector ++. , , , , . .

NumericVector:

Rcpp:: NumericVector std::vector?

++.

#include <iostream>

void func1(double* a) // The pointer is passed by value.
{
    for (int i=0; i<3; ++i)
        a[i] *= 2;
}

void func2(double*& a) // The pointer is passed by reference.
{
    for (int i=0; i<3; ++i)
        a[i] *= 2;
}

void print(double* a)
{
    std::cout << "Start print:" << std::endl;
    for (int i=0; i<3; ++i)
        std::cout << a[i] << std::endl;
}

int main()
{
    double* x = new double[3];

    // Set the values with 1, 2, and 3.
    for (int i = 0; i<3; ++i)
        x[i] = i+1;

    print(x);
    func1(x);
    print(x);

    // Reset the values with 1, 2, and 3.
    for (int i = 0; i<3; ++i)
        x[i] = i+1;

    // This block shows the same behavior as the block above.
    print(x);
    func2(x);
    print(x);

    delete[] x;
}
0

Source: https://habr.com/ru/post/1694850/


All Articles