创建 Rcpp 矩阵列表
Create a list of Rcpp matrices
我想创建一个我正在循环更新的矩阵列表,然后 return 它到 R。我有
std::vector<IntegerMatrix> zb_list;
和
IntegerMatrix tb(J,nmax), zb(J,nmax);
在循环之前。在循环内,我更新 zb
然后
zb_list.push_back(zb);
我也有
Rcout << (zb_list[itr]) << "\n";
Rcout << (zb) << "\n\n";
其中 itr
计算迭代次数。这些都证实 zb
在循环内发生变化,并且 zb_list
跟踪它。
然后我returnzb_list
循环之后。在 R 中访问结果时,列表包含相同 zb
的副本,即循环中计算的最后一个。我怀疑有一些通过引用传递......但无法弄清楚。我不太了解发生了什么(尝试使用 return(wrap(zb_list))
没有运气)但显然出了点问题。还使用 List zb_list;
来定义它,但没有帮助。有什么建议吗?
编辑:这是最小的工作示例:
#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 ) ++ ;
zb_list.push_back(zb);
Rcout << (zb) << (zb_list[itr]) << "\n\n";
++itr;
}
return List::create(_["zb"] = zb,
_["zb_list"] = zb_list);
}
/*** R
res <- test_weird()
res$zb_list
*/
这是外观时的输出 运行:
0 0
0 1
0 0
0 1
1 0
0 1
1 0
0 1
... 这是 R:
的输出
> res$zb_list
[[1]]
[,1] [,2]
[1,] 1 0
[2,] 0 1
[[2]]
[,1] [,2]
[1,] 1 0
[2,] 0 1
如您所见,列表中的两项都是循环中的最后一项 zb
。
问题是 push_back(something)
复制了 something
。但是如果 something
是一个指针,那么随后的更改将影响该指针的所有副本。在普通 C++ 中:
#include <vector>
#include <iostream>
int main() {
std::vector<int*> v;
int* p = new int;
for (int i = 0; i < 2; ++i) {
*p = i;
v.push_back(p);
std::cout << *p << " " << *v[i] << std::endl;
}
std::cout << *v[0] << " " << *v[1] << std::endl;
return 0;
}
生产
$ ./pointer_fun
0 0
1 1
1 1
因此,如果 something
是一个指针(如对象),所有 Rcpp 对象都是这种情况,那么您需要对象的深度 copy/clone,即
zb_list.push_back(clone(zb));
我想创建一个我正在循环更新的矩阵列表,然后 return 它到 R。我有
std::vector<IntegerMatrix> zb_list;
和
IntegerMatrix tb(J,nmax), zb(J,nmax);
在循环之前。在循环内,我更新 zb
然后
zb_list.push_back(zb);
我也有
Rcout << (zb_list[itr]) << "\n";
Rcout << (zb) << "\n\n";
其中 itr
计算迭代次数。这些都证实 zb
在循环内发生变化,并且 zb_list
跟踪它。
然后我returnzb_list
循环之后。在 R 中访问结果时,列表包含相同 zb
的副本,即循环中计算的最后一个。我怀疑有一些通过引用传递......但无法弄清楚。我不太了解发生了什么(尝试使用 return(wrap(zb_list))
没有运气)但显然出了点问题。还使用 List zb_list;
来定义它,但没有帮助。有什么建议吗?
编辑:这是最小的工作示例:
#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 ) ++ ;
zb_list.push_back(zb);
Rcout << (zb) << (zb_list[itr]) << "\n\n";
++itr;
}
return List::create(_["zb"] = zb,
_["zb_list"] = zb_list);
}
/*** R
res <- test_weird()
res$zb_list
*/
这是外观时的输出 运行:
0 0
0 1
0 0
0 1
1 0
0 1
1 0
0 1
... 这是 R:
的输出> res$zb_list
[[1]]
[,1] [,2]
[1,] 1 0
[2,] 0 1
[[2]]
[,1] [,2]
[1,] 1 0
[2,] 0 1
如您所见,列表中的两项都是循环中的最后一项 zb
。
问题是 push_back(something)
复制了 something
。但是如果 something
是一个指针,那么随后的更改将影响该指针的所有副本。在普通 C++ 中:
#include <vector>
#include <iostream>
int main() {
std::vector<int*> v;
int* p = new int;
for (int i = 0; i < 2; ++i) {
*p = i;
v.push_back(p);
std::cout << *p << " " << *v[i] << std::endl;
}
std::cout << *v[0] << " " << *v[1] << std::endl;
return 0;
}
生产
$ ./pointer_fun
0 0
1 1
1 1
因此,如果 something
是一个指针(如对象),所有 Rcpp 对象都是这种情况,那么您需要对象的深度 copy/clone,即
zb_list.push_back(clone(zb));