如何使用 RAII 包装返回错误代码的 C 分配
How to wrap C allocation returning error code using RAII
我知道有人问过类似的问题elsewhere,但我找不到适合我的函数签名的答案。
考虑这对典型的 C 函数:
int initFoo(Options options, Foo* foo);
void freeFoo(Foo* foo);
initFoo
采用一些选项和指向未初始化 Foo
结构的指针。它初始化此结构和 returns 指示初始化是否成功的结果代码。 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
结构,然后分两步显式释放和删除它。有什么想法吗?
你不能把 Foo
包裹在 class 中吗?
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
动态分配它。
我知道有人问过类似的问题elsewhere,但我找不到适合我的函数签名的答案。
考虑这对典型的 C 函数:
int initFoo(Options options, Foo* foo);
void freeFoo(Foo* foo);
initFoo
采用一些选项和指向未初始化 Foo
结构的指针。它初始化此结构和 returns 指示初始化是否成功的结果代码。 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
结构,然后分两步显式释放和删除它。有什么想法吗?
你不能把 Foo
包裹在 class 中吗?
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
动态分配它。