代码之家  ›  专栏  ›  技术社区  ›  Serge Rogatch

用于唯一\u ptr的有状态自定义删除程序

  •  -1
  • Serge Rogatch  · 技术社区  · 7 年前

    我使用内存池进行更快的分配&释放。内存池的 Release()

    现在,我想将从内存池获得的数组指针存储在 unique_ptr . 数组大小可变,因此我需要一个存储数组大小的有状态自定义删除程序。

    你能提供关于如何声明这样一个问题的示例代码吗 独特的 ?

    更新:在Artyer的提示让我明白之后,以下是我尝试过的:

    template<typename T> struct MPSingleDeleter {
      void operator()(T *p) {
        p->~T();
        MemPool::Instance().Release(p, sizeof(T));
      }
    };
    
    template<typename T> struct MPArrayDeleter {
      size_t _nItems;
    
      explicit MPArrayDeleter(const size_t nItems) : _nItems(nItems) {
      }
    
      void operator()(T *p) {
        for (size_t i = 0; i < _nItems; i++) {
          p[i].~T();
        }
        MemPool::Instance().Release(p, _nItems * sizeof(T));
      }
    };
    
    template <typename T> using SingleUP = std::unique_ptr<T, MPSingleDeleter<T>>;
    template <typename T> using ArrayUP = std::unique_ptr<T[], MPArrayDeleter<T>>;
    
    struct MemHelper {
      template<typename T, typename ...Args>  static T* NewSingle(Args&&... args) {
        void * const p = MemPool::Instance().Acquire(sizeof(T));
        ::new (p) T(std::forward<Args>(args)...);
        return static_cast<T*>(p);
      }
    
      template<typename T, typename ...Args> static T* NewArray(const size_t nItems, Args&&... args) {
        T *p = static_cast<T*>(MemPool::Instance().Acquire(nItems * sizeof(T)));
        for (size_t i = 0; i < nItems; i++) {
          void * const pv = static_cast<void *>(p + i);
          ::new (pv) T(std::forward<Args>(args)...);
        }
        return p;
      }
    
      template<typename T, typename ...Args> static SingleUP<T> MakeSUP(Args&&... args) {
        return SingleUP<T>(NewSingle<T>(std::forward<Args>(args)...));
      }
    
      template<typename T, typename ...Args> static ArrayUP<T> MakeAUP(const size_t nItems, Args&&... args) {
        return ArrayUP<T>(NewArray<T>(nItems, std::forward<Args>(args)...), MPArrayDeleter<T>(nItems));
      }
    };
    

    现在宣布 独特的 变量与以下内容一样简单:

    // Array of double
    ArrayUP<double> pBuffer = MemHelper::MakeAUP<double>(2ui64 * nItems);
    // Single Connection
    SingleUP<Connection> pConn = MemHelper::MakeSUP<Connection>(ioContext);
    
    0 回复  |  直到 7 年前
        1
  •  2
  •   Artyer    7 年前

    通常在内存池中存储分配数据之前的大小,因此只需传递一个从指针获取大小的无状态删除程序。

    不过,您可以轻松地执行以下操作:

    #include <memory>
    
    struct pool_deleter {
        std::size_t size;
    
        template<class T>
        void operator()(T* ptr) noexcept {
            std::destroy_n(ptr, size);
            Release(ptr, size * sizeof(T));
        }
    };
    
    template<class T>
    using pool_ptr = std::unique_ptr<T, pool_deleter>;
    
    // Used like:
    std::size_t n = /* ... */;
    T* ptr_ = /* Allocate and construct n objects from pool  */;
    pool_ptr<T> ptr{ptr_, pool_deleter{n}};  // Pass the custom deleter as an argument