Rcpp 中值和引用参数之间的差异
Difference between value and reference args in Rcpp
考虑以下 2 个函数:
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
作为引用参数,而func2
将其作为值。如果这是常规C++,我会将其理解为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
和func2
的行为方式相同。
这是什么原因呢?通常,通过引用还是按值将参数传递给 Rcpp 函数更好?
首先,两个函数都返回一个未分配给任何变量的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
行为的有用知识:
我应该更喜欢 Rcpp::NumericVector 而不是 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;
}
相关文章:
- 派生类(构造函数具有参数)和基类(构造函数缺少参数)之间没有可行的转换
- 在 C 和 C++ 中作为函数参数,int **a 和 int a[][] 之间有什么确切的区别
- C++模板参数之间的比较似乎被忽略了
- 在不同的模板参数包之间分发非类型参数包
- 折叠表达式和参数包:static_assert 内 Args&& 和 Args 之间的区别
- 将函数作为参数传递的两种方式之间的区别
- C++ 和 Lua 函数之间的交互与 3D 矢量参数
- 大括号和括号之间的参数计算顺序
- RVALUE参考与const lVALUE参考作为参数之间的混淆
- 有没有办法根据模板参数的类型在不同的类实现之间进行选择
- 使用运行时参数与编译时参数在类之间共享代码
- Rcpp 中值和引用参数之间的差异
- 作为参数的'char *args[]'和'char **argv'之间的差异
- By-ref 参数:这是 std::thread 和 std::bind 之间的不一致吗?
- 是否可以找到两个模板参数之间表达式的类型
- 函数参数和临时变量之间复制构造函数的奇怪行为
- 有没有一种方法可以在基于枚举的可变参数模板函数之间进行选择,这比将函数包装在结构中更简单
- 从 1 中创建新的字符 * 作为参数,元素位于 2 个索引之间
- C - 编译器如何以参数为参数的过载函数在超载函数之间决定
- 在UWP页面之间传递参数的正确方法