在 Rcpp 中初始化 NumericMatrix class 成员后出现意外输出
unexpeced output after initializing a NumericMatrix class member in Rcpp
关于使用 myclass::fill_values
调整 NumericMatrix
类型 NumericMatrix
class myclass
(使用 RCPP_EXPOSED_CLASS
调用),我似乎是影响另一个成员 b
,莫名其妙地与 a
具有相同的值。
Rcpp 代码为:
#include <Rcpp.h>
using namespace Rcpp ;
class myclass{
public:
NumericMatrix a;
NumericMatrix b;
void init(const int&, const int&);
void fill_values(const int&, const int&, const double&);
};
void myclass::init(const int& nrow, const int& ncol){
NumericMatrix numeric_zeros(nrow,ncol);
for (int i = 0 ; i < nrow ; ++i){
for (int j = 0; j < ncol ; ++j){
numeric_zeros(i,j) = 0.0;
}
}
a = numeric_zeros;
b = numeric_zeros;
}
void myclass::fill_values(const int& nrow, const int& ncol, const double& value){
for (int i = 0 ; i < nrow ; ++i){
for (int j = 0; j < ncol ; ++j){
a(i,j) = value;
}
}
}
RCPP_EXPOSED_CLASS(myclass)
// [[Rcpp::export]]
NumericMatrix simple(const int& nrow, const int& ncol, const double& value){
myclass mymember;
mymember.init(nrow,ncol);
mymember.fill_values(nrow,ncol,value);
return(mymember.b);
}
R
输出是:
> simple(2,2,15.0)
[,1] [,2]
[1,] 15 15
[2,] 15 15
>
我怀疑错误源于我的初始化函数myclass::init
,但我一直无法找到错误。
我的代码有什么问题,有人可以建议初始化 NumericMatrix/Vector
class 成员的最佳方法吗?
我不太清楚为什么会这样,但我可以提出一些更改建议:
- 去掉你的
init
成员函数 - NumericMatrix
对象默认用 0
初始化,所以不需要遍历每个元素并自己执行此操作。即使忽略循环,您也可以通过直接在 member initializer list 中初始化 a
和 b
来避免创建中间对象(不仅仅是 numeric_zeros
)。这通常建议用于非整数数据类型(例如 NumericMatrix
)。
- 就您的示例而言,您可以摆脱
fill_values
方法并仅在您自己的构造函数中实现其功能(而不是使用编译器生成的构造函数)。
考虑到以上几点,这里有一个可能的实现:
#include <Rcpp.h>
class myclass2 {
public:
myclass2(int nrow_, int ncol_, double value_ = 0.0)
: a(nrow_, ncol_), b(nrow_, ncol_)
{
for (int i = 0; i < nrow_; i++) {
a(i, Rcpp::_) = Rcpp::NumericVector(ncol_, value_);
}
}
Rcpp::NumericMatrix a;
Rcpp::NumericMatrix b;
};
RCPP_EXPOSED_CLASS(myclass2)
// [[Rcpp::export("simplea2")]]
Rcpp::NumericMatrix simplea(int nrow, int ncol, double value){
myclass2 mymember(nrow, ncol, value);
return(mymember.a);
}
// [[Rcpp::export("simpleb2")]]
Rcpp::NumericMatrix simpleb( int nrow, int ncol, double value){
myclass2 mymember(nrow, ncol, value);
return(mymember.b);
}
在 myclass2
源文件中,我定义了 simplea2
和 simpleb2
(return 数据成员分别是 a
和 b
);并对包含 myclass
原始定义的源文件执行相同操作,即
/*
* Class definition from your question...
*/
// [[Rcpp::export]]
Rcpp::NumericMatrix simplea(const int nrow, const int ncol, const double value){
myclass mymember;
mymember.init(nrow,ncol);
mymember.fill_values(nrow,ncol,value);
return(mymember.a);
}
// [[Rcpp::export]]
Rcpp::NumericMatrix simpleb(const int nrow, const int ncol, const double value){
myclass mymember;
mymember.init(nrow,ncol);
mymember.fill_values(nrow,ncol,value);
return(mymember.b);
}
比较这两个 类,
R> simplea(2,2,15.0)
[,1] [,2]
[1,] 15 15
[2,] 15 15
R> simpleb(2,2,15.0)
[,1] [,2]
[1,] 15 15
[2,] 15 15
##
R> simplea2(2,2,15.0)
[,1] [,2]
[1,] 15 15
[2,] 15 15
R> simpleb2(2,2,15.0)
[,1] [,2]
[1,] 0 0
[2,] 0 0
您可以看到 b
不再受对 a
所做更改的影响。
关于使用 myclass::fill_values
调整 NumericMatrix
类型 NumericMatrix
class myclass
(使用 RCPP_EXPOSED_CLASS
调用),我似乎是影响另一个成员 b
,莫名其妙地与 a
具有相同的值。
Rcpp 代码为:
#include <Rcpp.h>
using namespace Rcpp ;
class myclass{
public:
NumericMatrix a;
NumericMatrix b;
void init(const int&, const int&);
void fill_values(const int&, const int&, const double&);
};
void myclass::init(const int& nrow, const int& ncol){
NumericMatrix numeric_zeros(nrow,ncol);
for (int i = 0 ; i < nrow ; ++i){
for (int j = 0; j < ncol ; ++j){
numeric_zeros(i,j) = 0.0;
}
}
a = numeric_zeros;
b = numeric_zeros;
}
void myclass::fill_values(const int& nrow, const int& ncol, const double& value){
for (int i = 0 ; i < nrow ; ++i){
for (int j = 0; j < ncol ; ++j){
a(i,j) = value;
}
}
}
RCPP_EXPOSED_CLASS(myclass)
// [[Rcpp::export]]
NumericMatrix simple(const int& nrow, const int& ncol, const double& value){
myclass mymember;
mymember.init(nrow,ncol);
mymember.fill_values(nrow,ncol,value);
return(mymember.b);
}
R
输出是:
> simple(2,2,15.0)
[,1] [,2]
[1,] 15 15
[2,] 15 15
>
我怀疑错误源于我的初始化函数myclass::init
,但我一直无法找到错误。
我的代码有什么问题,有人可以建议初始化 NumericMatrix/Vector
class 成员的最佳方法吗?
我不太清楚为什么会这样,但我可以提出一些更改建议:
- 去掉你的
init
成员函数 -NumericMatrix
对象默认用0
初始化,所以不需要遍历每个元素并自己执行此操作。即使忽略循环,您也可以通过直接在 member initializer list 中初始化a
和b
来避免创建中间对象(不仅仅是numeric_zeros
)。这通常建议用于非整数数据类型(例如NumericMatrix
)。 - 就您的示例而言,您可以摆脱
fill_values
方法并仅在您自己的构造函数中实现其功能(而不是使用编译器生成的构造函数)。
考虑到以上几点,这里有一个可能的实现:
#include <Rcpp.h>
class myclass2 {
public:
myclass2(int nrow_, int ncol_, double value_ = 0.0)
: a(nrow_, ncol_), b(nrow_, ncol_)
{
for (int i = 0; i < nrow_; i++) {
a(i, Rcpp::_) = Rcpp::NumericVector(ncol_, value_);
}
}
Rcpp::NumericMatrix a;
Rcpp::NumericMatrix b;
};
RCPP_EXPOSED_CLASS(myclass2)
// [[Rcpp::export("simplea2")]]
Rcpp::NumericMatrix simplea(int nrow, int ncol, double value){
myclass2 mymember(nrow, ncol, value);
return(mymember.a);
}
// [[Rcpp::export("simpleb2")]]
Rcpp::NumericMatrix simpleb( int nrow, int ncol, double value){
myclass2 mymember(nrow, ncol, value);
return(mymember.b);
}
在 myclass2
源文件中,我定义了 simplea2
和 simpleb2
(return 数据成员分别是 a
和 b
);并对包含 myclass
原始定义的源文件执行相同操作,即
/*
* Class definition from your question...
*/
// [[Rcpp::export]]
Rcpp::NumericMatrix simplea(const int nrow, const int ncol, const double value){
myclass mymember;
mymember.init(nrow,ncol);
mymember.fill_values(nrow,ncol,value);
return(mymember.a);
}
// [[Rcpp::export]]
Rcpp::NumericMatrix simpleb(const int nrow, const int ncol, const double value){
myclass mymember;
mymember.init(nrow,ncol);
mymember.fill_values(nrow,ncol,value);
return(mymember.b);
}
比较这两个 类,
R> simplea(2,2,15.0)
[,1] [,2]
[1,] 15 15
[2,] 15 15
R> simpleb(2,2,15.0)
[,1] [,2]
[1,] 15 15
[2,] 15 15
##
R> simplea2(2,2,15.0)
[,1] [,2]
[1,] 15 15
[2,] 15 15
R> simpleb2(2,2,15.0)
[,1] [,2]
[1,] 0 0
[2,] 0 0
您可以看到 b
不再受对 a
所做更改的影响。