将 std::unique_ptr 与自定义分配器一起使用,以包装原始指针

Using std::unique_ptr with a custom deallocator for wrapping raw pointers

本文关键字:包装 指针 原始 一起 分配器 unique std ptr 自定义      更新时间:2023-10-16

我正在尝试将libsvm用于某个复杂的应用程序,并且由于libsvm主要是C库,因此在加载某些数据后,必须使用自定义API函数来释放内存。我的意思是:

struct svm_model *model;
model = svm_load_model("path to model file");
//do some processing
svm_free_and_destroy_model(&this->model);

这些是我使用的libsvm API函数的定义:

struct svm_model *svm_load_model(const char *model_file_name);
void svm_free_and_destroy_model(struct svm_model **model_ptr_ptr);

虽然这工作得很好,但如果在我处理模型数据时发生异常,那么我最终会出现内存泄漏。为了防止这种情况,我将上面的代码包装在一个类中,我在构造函数中调用svm_load_model,在析构函数中调用svm_free_and_destroy_model

现在,由于我们处于智能指针的时代,我想变得更有创意,并且以某种方式将模型变量声明为std::unique_ptr,将指向svm_free_and_destroy_model的指针设置为自定义分配器,但不幸的是,我无法弄清楚这样的事情是否可行。目前,我什至无法编译它,我只是在黑暗中拍摄。以下是我认为它应该如何工作:

std::unique_ptr<struct svm_model *, /* what should I add here? */ > model (svm_load_model("path to model file"), svm_free_and_destroy_model);

std::unique_ptr的类型参数需要T,而不是T *。使用 lambda 调用删除程序函数。

std::unique_ptr<svm_model, void(*)(svm_model *)> 
  p( svm_load_model( "path_to_model" ), 
     []( svm_model *mdl ) { 
       svm_free_and_detroy_model( &mdl ); 
     } 
   );

由于VS2010没有实现无状态lambda到函数指针的转换,因此您必须使用std::function才能使其正常工作。

std::unique_ptr<svm_model, std::function<void(svm_model*)>>
  p( svm_load_model("path_to_model"), 
     []( svm_model *mdl ) {
       svm_free_and_destroy_model( &mdl );
     }
   );

unique_ptr删除器应该是一个只接受指针的函数,而不是指向指针的指针。你可以试试:

void svm_deleter(svm_model*& model)
{
    svm_free_and_detroy_model(&model);
}
....
std::unique_ptr< svm_model, void(*)(svm_model*&) >(
    svm_load_model("path to model file")
  , &svm_deleter
);