在 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 成员的最佳方法吗?

我不太清楚为什么会这样,但我可以提出一些更改建议:

  1. 去掉你的 init 成员函数 - NumericMatrix 对象默认用 0 初始化,所以不需要遍历每个元素并自己执行此操作。即使忽略循环,您也可以通过直接在 member initializer list 中初始化 ab 来避免创建中间对象(不仅仅是 numeric_zeros)。这通常建议用于非整数数据类型(例如 NumericMatrix)。
  2. 就您的示例而言,您可以摆脱 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 源文件中,我定义了 simplea2simpleb2(return 数据成员分别是 ab );并对包含 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 所做更改的影响。