如何使用 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 动态分配它。