Rcpp循环生成矩阵列表返回R时元素重复最后一个矩阵问题求助
解决Rcpp循环存储矩阵列表后所有元素均为最终值的问题
嘿,这个问题我之前也碰到过!核心原因其实是Rcpp里矩阵类的拷贝机制在搞鬼,咱们一步步理清楚:
为啥会出现这个问题?
Rcpp的IntegerMatrix(包括NumericMatrix这类矩阵类)本质是对R对象(SEXP)的包装,默认的拷贝操作是浅拷贝——也就是说,当你执行zb_list.push_back(zb)时,并没有把zb的数值复制一份新的存进列表,只是把指向zb底层内存的"引用"塞进去了。循环里你一直在修改同一个zb的内容,最后列表里所有元素都指向同一块内存,自然回到R里看到的全是最后一次修改后的结果。
怎么解决?
关键就是每次存进列表的时候,要生成zb的独立副本(深拷贝),而不是复用原来的内存。Rcpp给咱们提供了很方便的clone()方法,直接调用就能生成完全独立的新矩阵。
修改后的可运行代码
只需要改一行代码就行,看下面的示例:
#include <Rcpp.h> using namespace Rcpp; // [[Rcpp::export]] List test_weird(int ITRmax=2) { IntegerMatrix zb(2,2); std::vector<IntegerMatrix> zb_list; int itr = 0; while (itr < ITRmax) { zb( (1+itr)%2 ,(1+itr)%2 ) ++ ; // 重点:用clone()生成深拷贝再加入列表 zb_list.push_back(zb.clone()); Rcout << (zb) << (zb_list[itr]) << "\n\n"; ++itr; } return List::create(_["zb"] = zb, _["zb_list"] = zb_list); } /*** R res <- test_weird() res$zb_list
验证结果
运行这段代码后,R端的输出就正常了:
> res$zb_list [[1]] [,1] [,2] [1,] 0 0 [2,] 0 1 [[2]] [,1] [,2] [1,] 1 0 [2,] 0 1
和你循环里用Rcout打印的中间结果完全一致,每个列表元素都保留了对应循环步骤的矩阵状态。
另一种思路:每次循环创建新矩阵
如果你不想用clone(),也可以在每次循环里新建一个IntegerMatrix对象,把当前zb的数值复制进去再修改,比如:
while (itr < ITRmax) { // 新建独立矩阵,复制当前zb的内容 IntegerMatrix new_zb = clone(zb); new_zb( (1+itr)%2 ,(1+itr)%2 ) ++ ; zb_list.push_back(new_zb); // 更新原zb为新状态供下一次循环使用 zb = new_zb; ++itr; }
这种方式本质和用clone()是一样的,都是生成独立副本,只是写法不同而已。
内容的提问来源于stack exchange,提问作者passerby51
相关产品推荐
相关产品推荐

