我在工作中有一些旧版代码,它接收一个双指针并为其分配内存。一个简化的示例看起来像这样:
struct LegacyObj
{
int a;
double b;
};
void LegacyAllocator(LegacyObj** ppObj)
{
*ppObj = (LegacyObj*)malloc(sizeof(LegacyObj));
}
void LegacyDeleter(LegacyObj** ppObj)
{
free(*ppObj);
}
实际的LegacyAllocator函数有大约100行代码,将文件读取和创建LegacyObj指针的链表混合在一起。目前来说我无法重写这个函数。然而,我希望能让使用这个函数更加安全,避免因为异常等情况导致内存泄漏。我想出的第一个解决方案是将其封装成一个类,在构造函数和析构函数中处理调用遗留函数。
class RAIIWrapper
{
public:
RAIIWrapper()
:obj{nullptr}
{
::LegacyAllocator(&obj);
}
RAIIWrapper(RAIIWrapper&& that)
: obj{ that.obj}
{
that.obj = nullptr;
}
RAIIWrapper& operator=(RAIIWrapper&& that)
{
RAIIWrapper copy{std::move(that)};
std::swap(obj, copy.obj);
return *this;
}
~RAIIWrapper ()
{
::LegacyDeleter(&obj);
}
private:
LegacyObj* obj;
};
但是我很好奇 - 是否有一种方法可以使用std::shared_ptr
或std::unique_ptr
来完成这个任务呢?我还没有找到一种解决方法,而又不需要保留传递给LegacyAllocator的原始指针。
unique_ptr
和shared_ptr
不接受分配器,它们只接受删除器。您可以使用LegacyAllocator(&obj)
自己分配指针,并为unique_ptr
/shared_ptr
创建一个删除器函数,该函数在其operator()
中调用LegacyDeleter(&p)
。 - David