我在工作中有一些遗留代码,它接受一个双指针并为其分配内存.缩短的例子看起来像这样:
struct LegacyObj
{
int a;
double b;
};
void LegacyAllocator(LegacyObj** ppObj)
{
*ppObj = (LegacyObj*)malloc(sizeof(LegacyObj));
}
void LegacyDeleter(LegacyObj** ppObj)
{
free(*ppObj);
}
Run Code Online (Sandbox Code Playgroud)
实际LegacyAllocator功能〜100线和混合读取文件与创建LegacyObj指针链表,是不是我能够与现在重写脱身.但是,我想使这个函数的使用更安全一点,避免因异常和tc而导致的任何内存泄漏.我想出的第一个解决方案是将它包装在一个类中并处理调用ctor/dtor中的遗留函数.
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;
};
Run Code Online (Sandbox Code Playgroud)
但我很好奇 - 是否有办法使用std::shared_ptr
或std::unique_ptr
?我没有能够提出解决方案而不必将原始指针传递给LegacyAllocator.
是的,您可以将自定义删除器与std::unique_ptr
或 一起使用std::shared_ptr
,例如:
struct Deleter {
void operator()(LegacyObj *p) const {
LegacyDeleter(&p);
}
};
std::unique_ptr<LegacyObj, Deleter> MakeLegacyObj() {
LegacyObj *p = 0;
LegacyAllocator(&p);
return std::unique_ptr<LegacyObj, Deleter>(p);
}
std::unique_ptr<LegacyObj, Deleter> p = MakeLegacyObj();
Run Code Online (Sandbox Code Playgroud)
而且,正如 @Dave 正确指出的那样,这shared_ptr
也适用于:
std::shared_ptr<LegacyObj> p = MakeLegacyObj();
Run Code Online (Sandbox Code Playgroud)