Rcpp中值和参考args之间的差异

时间:2018-03-14 08:01:43

标签: c++ r rcpp

考虑这两个功能:

docker-compose -f docker-compose.yml -f docker-compose.development.yml up -d

唯一的区别是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; }") func1作为参考参数,而x将其作为值。如果这是常规C ++,我会理解这一点,因为允许func2更改调用代码中func1的值,而x中不会发生这种情况。

然而:

func2

因此,就参数的副作用而言,> 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 func1的行为方式相同。

这是什么原因?通常,通过引用或值传递参数到Rcpp函数是否更好?

1 个答案:

答案 0 :(得分:0)

首先,两个函数都返回一个未分配给任何变量的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)

其次,NumericVector在C ++函数中表现为指针。指针为您提供存储值的地址,并且为了能够更改该地址的值,您只需知道地址,但您不需要能够修改地址本身。因此,将指针传递给值或通过引用传递它没有区别。

此主题包含有关NumericVector的行为的有用知识:

Should I prefer Rcpp::NumericVector over std::vector?

下面的程序演示了C ++中的相同行为。

#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;
}
相关问题