【问题标题】:Initialise a functor passed into a unique_ptr custom deleter初始化传递给 unique_ptr 自定义删除器的函子
【发布时间】:2015-01-17 14:39:56
【问题描述】:

我正在使用 RAII 来管理我的代码中的资源,方法是使用 std::unique_ptr 和自定义删除器。到目前为止,这相对简单,但我现在想为需要访问现有托管资源的资源添加一个 RAII 包装器,作为其清理函子的一部分。

为了分解它,我有一个类具有 RAII 管理的资源,并且可以获取依赖它的其他资源:

struct CloseHandleFunctor
{
    typedef HANDLE pointer;
    void operator()(const HANDLE h)
    {
        ::CloseHandle(h);
    }
};

using AutoHandle = std::unique_ptr<HANDLE, CloseHandleFunctor>;

class Helper
{
public:
    // acquires a resource associated with h_
    Resource get_resource();
    // releases the resource acquired by get_resource()
    void release_resource(const Resource res);
    // ...
private:
    AutoHandle h_;
};

我想包装由Helper::get_resource() 返回的Resource,但不知道如何使用std::unique_ptr 提供对仿函数内Helper 类实例的访问:

struct ReleaseResourceFunctor
{
    typedef Resource pointer;
    void operator()(Helper h, const Resource r)
    {
        h.release_resource(r);
    }
};

using AutoResource = std::unique_ptr<Resource, ReleaseResourceFunctor>;
   // no way to pass the instance of Helper ~~~^

这就是我想使用它的方式:

int main()
{
    Helper h;

    {
        AutoResource res(h.get_resource());
    }
    // h.release_resource() gets called
}

【问题讨论】:

  • 这一步似乎不可能,你可能必须get the deleter 并在deleter 结构中有一个函数来设置helper 类。
  • 这些是嵌套的生命周期,我看没问题?
  • ReleaseResourceFunctor 中存储指向Helper 实例的引用/指针?

标签: c++ unique-ptr raii


【解决方案1】:

按照JoachimCasey 的建议,我可以通过在仿函数中存储指向Helper 类实例的指针来使其工作:

struct ReleaseResourceFunctor
{
    typedef Resource pointer;

    Helper *helper_;

    ReleaseResourceFunctor()
        : helper_(nullptr)
    {
    }

    void setHelper(Helper * const h)
    {
        helper_ = h;
    }

    void operator()(const Resource r)
    {
        if (helper_ != nullptr)
        {
            helper_->release_resource(r);
        }
    }
};

...然后通过在构造std::unique_ptr之后分配帮助器实例:

int main()
{
    Helper h;

    {
        AutoResource res(h.get_resource());
        res.get_deleter().setHelper(&h);
    }
    // h.release_resource() gets called as expected
}

它看起来有点脆弱(记得每次都分配帮助器实例),但它确实按预期工作。

【讨论】:

    猜你喜欢
    • 2014-08-27
    • 1970-01-01
    • 2013-03-30
    • 1970-01-01
    • 1970-01-01
    • 2020-02-25
    • 1970-01-01
    • 2015-08-15
    • 1970-01-01
    相关资源
    最近更新 更多