创建std :: shared_ptr对象并将其返回到R端(Rcpp)

Bar*_*art 2 c++ r rcpp

我正在尝试使用Rcpp为C++脚本编写R绑定.其中一个功能需要a std::shared_ptr object.我发现很难初始化std::shared_ptrobj并将其作为Rcpp::XPtr对象返回到R端.

我试过(最小的例子):

#include <iostream>
#include <memory>
#include <Rcpp.h> 
using namespace Rcpp;
using std::cout;


class TestClass {
  public:
    int value;

    TestClass(int initial_val) {
      value = initial_val;
    };

};


//[[Rcpp::export]]
SEXP get_test_obj() {
  Rcpp::XPtr<std::shared_ptr<TestClass>> ptr(std::make_shared<TestClass>(5), true);
  return ptr;
};
Run Code Online (Sandbox Code Playgroud)

但是得到以下错误:

 no matching function for call to 'Rcpp::XPtr<std::shared_ptr<TestClass> >::XPtr(std::shared_ptr<TestClass>, bool)'
Run Code Online (Sandbox Code Playgroud)

关于如何做到这一点的任何想法?或者我错了吗?

Rom*_*ois 7

来自@ d3coy的答案几乎包含所有信息.Rcpp::XPtr是一个模板智能指针类,它的参数是指针类,而不是它指向的类.所以a Rcpp::XPtr<std::shared_ptr<TestClass>>将是一个智能指针std::shared_ptr<TestClass>*.请注意*,这是重要的一点.

当a shared_ptr超出范围时,如果它是原始指针的最后一个持有者,则原始指针可能会被删除.这绝对不是你想要的.

相反,您可以创建一个原始指针,newXPtr使用它进行输入.delete当垃圾收集器收集R对象时,这个指针将得到d XPtr,这是你在处理外部指针时通常想要的.

我知道当前的指导方针是尽可能使用make_uniquemake_shared不是new在这种情况下你需要new.聪明才智来自于XPtr,如果你将shared_ptr它们混合起来,它们就会妨碍彼此.


小智 6

我怀疑R方会期望将std :: shared_ptr传递给它.我假设你的源代码中的其他一些代码依赖于std :: shared_ptr,但你想将内部原始指针传递给R.我还假设std :: shared_ptr的生命周期在你的代码中得到了更好的管理,因为所呈现的代码会使std :: shared_ptr在函数之后超出范围并在下一次取消引用时崩溃.

在任何情况下,如果你只想将内部原始指针传递给R,你就会这样做(设计):

//[[Rcpp::export]]
SEXP get_test_obj() {
  std::shared_ptr<TestClass> s_ptr = std::make_shared<TestClass>(5);
  Rcpp::XPtr<TestClass> x_ptr(s_ptr.get(), true);
  return x_ptr;
};
Run Code Online (Sandbox Code Playgroud)