有条件的自定义删除器,用于unique_ptr

时间:2019-08-23 08:32:29

标签: c++ memory c++17 smart-pointers

我正在使用内存池进行更快的分配和释放。内存池的sysctl -w net.core.netdev_budget_usecs=8000 sysctl: cannot stat /proc/sys/net/core/netdev_budget_usecs: Aucun fichier ou dossier de ce type 操作需要释放指针和分配的字节数。

现在,我要将从内存池获得的数组指针存储在Release()中。数组的大小可变,因此我需要一个有状态的自定义删除器,用于存储数组的大小。

您能提供有关如何声明这样的unique_ptr的示例代码吗?

更新:在Artyer的提示让我很清楚之后,这是我尝试的方法:

unique_ptr

现在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)); } }; 变量的声明非常简单:

unique_ptr

1 个答案:

答案 0 :(得分:2)

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

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

#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