我意识到类似的问题已被问到elsewhere,但我找不到一个非常适合我的功能签名的答案。
考虑这对典型的C函数:
int initFoo(Options options, Foo* foo);
void freeFoo(Foo* foo);
initFoo
需要一些选项和指向未初始化Foo
结构的指针。它初始化此结构并返回一个结果代码,指示初始化是否成功。 freeFoo
释放初始化的Foo
结构。
现在假设我想在我的C ++代码中使用这些C函数。我想使用RAII,因此我需要构建一个unique_ptr<Foo>
,它会在销毁时自动调用freeFoo
。我能提出的最佳方法是:
template<typename T>
using lambda_unique_ptr = std::unique_ptr<T, std::function<void(T*)>>;
lambda_unique_ptr<Foo> createFoo(Options options) {
Foo* foo = new Foo();
const int resultCode = initFoo(options, foo);
if (resultCode != 0) throw ...;
return lambda_unique_ptr<Foo>(foo, [](Foo* foo) {
freeFoo(foo);
delete foo;
});
}
我确信必须有更优雅的解决方案。理想情况下,更具功能性的东西不需要这么多单独的步骤。我发现特别难看的是必须在堆上显式分配Foo
结构,然后显式释放并分两步删除它。有什么想法吗?
答案 0 :(得分:3)
你不能将Foo
包裹在课程中吗?
struct FooWrap {
Foo foo;
explicit FooWrap(Options options) {
if (initFoo(options, &this->foo))
throw ...;
}
~FooWrap() {
freeFoo(&this->foo);
}
// XXX: either implement or disable assignment and copy construction
};
现在,您可以选择是将FooWrap x(42);
定义为自动变量,还是选择是否使用new
动态分配它。