Rcpp 中的值和参考参数之间的差异 [英] Difference between value and reference args in Rcpp

查看:42
本文介绍了Rcpp 中的值和参考参数之间的差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑这两个函数:

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;
}")

唯一的区别是 func1x 作为参考参数,而 func2 将其作为值.如果这是常规的 C++,我会将其理解为允许 func1 在调用代码中更改 x 的值,而这不会发生在 func2.

The only difference is that func1 takes x as a reference parameter, whereas func2 takes it as a value. If this was regular C++, I'd understand this as func1 being allowed to change the value of x in the calling code, whereas this won't happen in 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

因此,就参数的副作用而言,func1func2 的行为方式相同.

So it looks like func1 and func2 behave the same way, as far as side-effects on the arguments are concerned.

这是什么原因?一般来说,给 Rcpp 函数传递参数是按引用好还是按值好?

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

推荐答案

首先,您的两个函数都返回一个 NumericVector,它没有分配给任何变量,因此没有被使用.下面的代码等同于您拥有的代码,因为您无论如何都会丢弃返回的 NumericVector.

First, both your functions return a NumericVector that is not being assigned to any variable, and therefore is not being used. The code below is equivalent to what you have, as you are discarding the returned NumericVector anyhow.

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++ 函数中表现为指针.指针为您提供了存储值的地址,为了能够更改该地址处的值,您只需要知道地址,但不需要修改地址本身的能力.因此,按值传递指针和按引用传递没有区别.

Second, a NumericVector behaves as a pointer in the C++ functions. The pointer gives you the address where the values are stored, and to be able to change the values at that address, you only need to know the address, but you don't need the ability to modify the address itself. Therefore, there is no difference in passing the pointer by value or passing it by reference.

此线程包含有关 NumericVector 行为的有用知识:

This thread contains useful knowledge on the behavior of NumericVector:

我应该更喜欢 Rcpp::NumericVector 而非 std::vector 吗?

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

The program below demonstrates the same behavior in 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;
}

这篇关于Rcpp 中的值和参考参数之间的差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆