问题描述
我引入了FreeGuard类,如果初始化失败,该类将清理资源:
struct Resource {...};
class FreeGuard {
public:
FreeGuard(Resource* r) : resource(r) {};
~FreeGuard() {
if (!dismissed) {
freeResource(resource);
}
}
void dismiss() { dismissed = true; }
private:
bool dismissed = false;
Resource* resource;
};
int init(Resource* r) {
FreeGuard guard(r);
if (...)
return -1;
if (...)
return -2;
...
if (...)
return -1000;
guard.dismiss();
return 0;
}
int freeResource(Resource* r) {...}
如何使用std智能指针实现相同的目的,从而不必继续编写FreeGuard类?
解决方法
您可以使用release()
的{{1}}功能。在处理非RAII资源(例如C库句柄)时,这是异常安全代码的常见模式:
unique_ptr
只需将您的#include <memory>
int freeResource(Resource* r) {...}
int init(Resource* r) {
std::unique_ptr<Resource,decltype(&freeResource)> guard(r,freeResource);
if (...)
return -1;
if (...)
return -2;
...
if (...)
return -1000;
guard.release(); // releases ownership,deleter will not be called
return 0;
}
函数重命名为其他名称(此处为free()
),以避免与标准freeResource()
函数冲突。