代码之家  ›  专栏  ›  技术社区  ›  Daniel Wolf deepee1

如何使用raii包装C分配返回错误代码

  •  0
  • Daniel Wolf deepee1  · 技术社区  · 8 年前

    我知道有人问过类似的问题 elsewhere 但我找不到适合我的函数签名的答案。

    考虑这对典型的C函数:

    int initFoo(Options options, Foo* foo);
    void freeFoo(Foo* foo);
    

    initFoo 接受一些选项和指向未初始化的 Foo 结构。它初始化此结构并返回一个结果代码,指示初始化是否成功。 freeFoo 释放已初始化的 FOO公司 结构。

    现在假设我想在C++代码中使用这些C函数。我想使用RAII,所以我需要构建一个 unique_ptr<Foo> 会自动呼叫 自由球 关于毁灭。我能想到的最佳方法是:

    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公司 堆上的结构,然后显式释放并分两步将其删除。有什么想法吗?

    1 回复  |  直到 8 年前
        1
  •  3
  •   melpomene    8 年前

    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