【问题标题】:managing raw memory with std::unique_ptr in C++在 C++ 中使用 std::unique_ptr 管理原始内存
【发布时间】:2012-09-09 12:34:12
【问题描述】:

我想要一个小类,用这个 API 管理原始内存

template<class allocator = std::allocator<char> >
class raw_memory
{
   static_assert(std::is_same<char, typename allocator::value_type>::value,
                 "raw_memory: allocator must deal in char");
public:
   raw_memory() = default;
   raw_memory(raw_memory&&) = default;
   raw_memory&operator=(raw_memory&&) = default;
   explicit raw_memory(size_t, allocator const& = allocator());
   ~raw_memory();       // deletes any memory
   char*get();          // returns pter to (begin of) memory
   void resize(size_t); // re-allocates if necessary, may delete old data
   size_t size() const; // returns number of bytes currently hold

   raw_memory(raw_memory const&) = delete;
   raw_memory&operator=(raw_memory const&) = delete;
   raw_memory(raw_memory&) = delete;
   raw_memory&operator=(raw_memory&) = delete;
};

模板参数allocator 允许不同的内存对齐选项。

我正在考虑使用std::unique_ptr&lt;char, Deleter&gt; 作为成员(或基数)(加上一个保存字节数的size_t)。什么用作删除器?还是有更好的方法来实现这一切?

【问题讨论】:

  • 将自定义删除器作为raw_memory 对象的一部分?
  • 如果你不需要分配器支持,你可以使用std::unique_ptr&lt;void, void(*)(void*)&gt; p(std::malloc(n), std::free);
  • 我猜你的意思是typename allocator::value_type
  • 好的,只需将std::free 替换为myfree,并编写自己的处理函数来推断需要传递给free 的原始地址的位置。您可以为一般情况编写自己的 cookie 类型标记,并在可用的情况下使用 posix_memalign
  • 您不必强制用户传递以char 类型进行通信的分配器。符合要求的分配器有一个名为 rebind 的嵌套模板,它将生成一个分配器来处理您实例化 rebind 的任何类型。

标签: c++ memory memory-management c++11 unique-ptr


【解决方案1】:

由于您让您的类的用户将分配器指定为类型参数,因此您必须在分配和解除分配时引用此参数。出于这个原因,@Kerrek 所做的推荐(虽然对函数指针的使用很棘手且很好)是无效的,因为您确实希望使用作为参数传递的分配器方法。

使用 unique_ptr 可以为您工作。正如您正确评论的那样,您必须提供自己的删除器,并且根据我上面的 cmets,它必须基于作为 agument 传递给模板的分配器类。

旁注:请注意您的模板声明中有语法错误。请参阅下面的示例代码以了解正确的语法(即您必须具有关键字“模板”):

template< class A = std::allocator<char> >
class raw_memory
{
private:
    A m_al;
    std::unique_ptr< char, std::function<void(char*)> > m_buffer;

public:
    raw_memory( size_t size, const A& al = A() )
        :m_al(al)
        ,m_buffer( m_al.allocate(size), [this, size](char* ptr){ m_al.deallocate(ptr,size); } )
        {
        }
};

注意事项:

  • 我使用 A 作为类型参数(我发现使用所有大写字母作为模板参数更具可读性)。
  • 使用 c++11 Lambda 表示法,我将删除器函子传递给 unique_ptr 的构造函数。这个函子有一个闭包状态(对 al 的引用和大小),将在删除期间使用。在闭包中,我将 this 指针(访问 m_al 所需)和大小 - 都按值。

【讨论】:

  • std::vector 有一个采用const allocator&amp; 的构造函数,即不需要按照您的建议采用非常量的allocator&amp;
  • @Walter - 你是对的。我试图避免分配器的成员(这只有在你没有调整大小的情况下才有意义)。我修改了我的答案,所以 raw_memory 有自己的分配器(构造为参数分配器的副本),并且 delete 函数的闭包现在有 'this' 指针
猜你喜欢
  • 2014-01-11
  • 2014-03-16
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-18
  • 1970-01-01
  • 2011-08-06
相关资源
最近更新 更多