【问题标题】:Wrap C allocation for RAII为 RAII 包装 C 分配
【发布时间】:2013-02-11 08:59:41
【问题描述】:

我有这些来自库的普通 C 函数:

struct SAlloc;
SAlloc *new_salloc();
void   free_salloc(SAlloc *s);

有什么方法可以在 C++ 中将其包装到智能指针 (std::unique_ptr) 或 RAII 包装器?

我主要对标准库的可能性感到好奇,而无需创建自己的包装器/类。

【问题讨论】:

  • 出于好奇,free_salloc() 返回什么?
  • 你可能会以某种方式使用 boost::intrusive_ptr。
  • 抱歉,这里应该是 void free_salloc()

标签: c++ c++11 smart-pointers


【解决方案1】:

是的,您可以为此重用 unique_ptr。只需制作一个自定义删除器即可。

struct salloc_deleter {
    void operator()(SAlloc* s) const {
        free_salloc(s); // what the heck is the return value for?
    }
}

using salloc_ptr = std::unique_ptr<SAlloc, salloc_deleter>;

【讨论】:

  • free_salloc 不是类型,所以不是。您可以使用std::unique_ptr&lt;SAlloc, SAlloc*(*)(SAlloc*)&gt;;,但您必须手动将free_salloc 传递给每个构造函数。
  • 带有 RAII 的返回值没有意义。它们是不相容的想法。 +1 顺便说一句!
  • 感谢您的回答。我曾问std::unique_ptr&lt;SAlloc, free_salloc&gt;是否也可以,但在发布后直接意识到错误,所以我删除了我的评论。
  • 您不需要 salloc_deleter 函子 - 您可以将 free_salloc 函数作为删除器传递(请参阅下面的答案)。
  • 这里可以使用std::integral_constant,详情请见this answer
【解决方案2】:

我喜欢 R. Martinho Fernandes 的回答,但这里有一个更短(但效率更低)的替代方案:

auto my_alloc = std::shared_ptr<SAlloc>(new_salloc(), free_salloc);

【讨论】:

    【解决方案3】:

    有什么方法可以在 C++ 中将其包装到智能指针 (std::unique_ptr) 或 RAII 包装器中?

    是的。您在这里需要一个工厂函数,它创建正确初始化智能指针的对象(并确保您始终正确构造指针实例):

    std::shared_ptr<SAlloc> make_shared_salloc()
    {
        return std::shared_ptr<SAlloc>(new_salloc(), free_salloc);
    }
    
    // Note: this doesn't work (see comment from @R.MartinhoFernandes below)
    std::unique_ptr<SAlloc> make_unique_salloc()
    {
        return std::unique_ptr<SAlloc>(new_salloc(), free_salloc);
    }
    

    您可以将调用这些函数的结果分配给其他智能指针(根据需要),这些指针将被正确删除。

    编辑: 或者,您可以为您的 SAlloc 指定 std::make_shared

    编辑 2: 第二个函数 (make_unique_salloc) 无法编译。需要实现一个替代的删除器函子来支持该实现。

    【讨论】:

    • free_salloc 不是default_delete&lt;SAlloc&gt; 的实例,因此第二个函数不会编译。
    • @R.MartinhoFernandes,我不确定您所说的“default_delete 实例”是什么意思。 shared_ptr/unique_ptr 可与任何删除器函子一起使用。 default_deletedefault_array_delete 是简单的函子,没有特殊要求,可以被任何其他尊重相同签名的函子类型替换。请参阅此处作为 OP 要求的示例:liveworkspace.org/code/16bBch$6
    • 错了。 unique_ptr 仅适用于 D 类型的删除器。 unique_ptr 仅适用于 default_delete 类型的删除器:liveworkspace.org/code/23jdye$0
    【解决方案4】:

    另一种变化:

    #include <memory>
    
    struct SAlloc {
      int x;
    };
    SAlloc *new_salloc() { return new SAlloc(); }
    void   free_salloc(SAlloc *s) { delete s; }
    
    struct salloc_freer {
      void operator()(SAlloc* s) const { free_salloc(s); }
    };
    typedef std::unique_ptr<SAlloc, salloc_freer> unique_salloc;
    template<typename... Args>
    unique_salloc make_salloc(Args&&... args) {
      auto retval = unique_salloc( new_salloc() );
      if(retval) {
        *retval = SAlloc{std::forward<Args>(args)...};
      }
      return retval;
    }
    
    int main() {
       unique_salloc u = make_salloc(7);
    }
    

    我在 SAlloc 中添加了一个主体,以及使其成为 http://sscce.org/ 的各种函数——这些的实现并不重要。

    只要你能看到SAlloc 的成员,上面将让你在创建SAlloc 的同时像在初始化列表中一样构造它们,如果你不传入任何参数它将整个 SAlloc struct 归零。

    【讨论】:

      猜你喜欢
      • 2018-11-18
      • 2011-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-06
      • 2021-03-15
      • 1970-01-01
      相关资源
      最近更新 更多