通过自定义分配器和删除器有效使用shared_ptr
Efficient usage of shared_ptr with custom allocator and deleter
目前我有以下代码用于使用自定义分配器和自定义删除器创建shared_ptr
(请参阅底部的要点,而依赖项定义在顶部(:
template <typename T>
class MPAllocator {
public:
//// The following will be the same for virtually all allocators.
typedef T * pointer;
typedef const T * const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
typedef std::size_t size_type;
typedef ptrdiff_t difference_type;
typedef std::true_type propagate_on_container_move_assignment;
//TODO: how shall the below be?
//typedef std::true_type propagate_on_container_copy_assignment;
//typedef std::true_type propagate_on_container_swap;
T * address(T& r) const noexcept {
return &r;
}
const T * address(const T& s) const noexcept {
return &s;
}
std::size_t max_size() const noexcept {
// The following has been carefully written to be independent of the definition of size_t and to avoid
// signed/unsigned warnings.
return (static_cast<std::size_t>(0) - static_cast<std::size_t>(1)) / sizeof(T);
}
//// The following must be the same for all allocators.
template <typename U>
struct rebind {
typedef MPAllocator<U> other;
};
template <class U, class ...Args> void construct(U* p, Args&&... args) const {
void * const pv = static_cast<void *>(p);
::new (pv) U(std::forward<Args>(args)...);
}
void destroy(T * const p) const {
p->~T();
}
// Default constructor, copy constructor, rebinding constructor, and destructor.
// Empty for stateless allocators.
MPAllocator() noexcept { }
// See https://stackoverflow.com/questions/54050890/how-to-utilize-template-copymove-constructor-and-assignment-operator
MPAllocator(const MPAllocator&) noexcept { }
template <typename U> MPAllocator(const MPAllocator<U>&) noexcept { }
~MPAllocator() noexcept { }
// The following will be different for each allocator.
T * allocate(const std::size_t n) const {
// The return value of allocate(0) is unspecified. Mallocator returns NULL in order to avoid depending on
// malloc(0)'s implementation-defined behavior (the implementation can define malloc(0) to return NULL, in which
// case the bad_alloc check below would fire). All allocators can return NULL in this case.
if (n == 0) {
return NULL;
}
// All allocators should contain an integer overflow check. The Standardization Committee recommends that
// std::length_error be thrown in the case of integer overflow.
if (n > max_size()) {
throw std::length_error("MPAllocator<T>::allocate() - Integer overflow.");
}
void * const pv = MemPool::Instance().Acquire(n * sizeof(T));
// Allocators should throw std::bad_alloc in the case of memory allocation failure.
if (pv == NULL) {
throw std::bad_alloc();
}
return static_cast<T*>(pv);
}
void deallocate(T * const p, const std::size_t n) const {
//TODO: check that the destructors of T get called, see http://www.cplusplus.com/reference/memory/allocator/deallocate/
MemPool::Instance().Release(p, n * sizeof(T));
}
// The following will be the same for all allocators that ignore hints.
template <typename U>
T * allocate(const std::size_t n, const U * /* const hint */) const {
return allocate(n);
}
};
template <typename T, typename U> inline
bool operator== (const MPAllocator<T>&, const MPAllocator<U>&) noexcept {
return true; // So long as our allocator doesn't have a state
}
template <typename T, typename U> inline
bool operator!= (const MPAllocator<T>&, const MPAllocator<U>&) noexcept {
return false;
}
template<typename T> struct MPSingleDeleter {
void operator()(T *p) {
if (p != nullptr) {
p->~T();
MemPool::Instance().Release(p, sizeof(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);
}
// Make SSP="Single Shared Pointer"
template<typename T, typename ...Args> static std::shared_ptr<T> MakeSSP(Args&&... args) {
return std::shared_ptr<T>(NewSingle<T>(std::forward<Args>(args)...), MPSingleDeleter<T>(), MPAllocator<T>());
}
}
这种方法的问题在于,我猜无状态MPSingleDeleter
和MPAllocator
类在shared_ptr
结构中占用了一些空间。
有没有办法将自定义删除器和分配器传递给shared_ptr
,而不会在每个shared_ptr
中占用空间?
你在这里试图平方圆:如果你想让你的shared_ptr
保留你在构造函数中获得的任意删除器,在析构时使用 - 你需要以某种方式将其存储在shared_ptr
中; 否则 - 删除时,您将无法选择使用每个类的默认值(例如静态(。
相关文章:
- CLANG 编译器 说:变量"PTR"可能未初始化
- 在以唯一ptr为值的C++映射中,动态内存何时会被销毁
- 将 ptr 传递给 ptr 到 A 作为参数传递给 A 的函数是不好的做法吗?
- 为共享 ptr 向量实现复制 c'tor?
- 字符和整数中 **(ptr+1) 的值差异
- C++:在不中断共享的情况下通过引用传递共享 PTR?
- 如何将派生类从基 ptr 分配给 nlohmann::json
- 引用 std::shared:ptr 以避免引用计数
- 为什么我不能在不进行任何转换的情况下将浮点数放入任何类型的 ptr 中?
- 在调用函数时,ptr** 和 ptr*& 之间是否有区别,或者首选C++?
- 另一种类型的智能ptr,比如具有弱refs的unique_ptr
- 尝试打印出 *ptr++ 的值,以了解它是如何工作的
- 如何控制共享 ptr 引用计数?
- dopen():不以 root 身份运行时"failed to map segment from shared object"
- C++中的指针否定 (!ptr == NULL)
- 从const ptr*转换为ptr*时出现问题
- 无法使用 libtool 将 -shared 参数传递给 g++
- boost::shared_ptr和std::shared-ptr的同居
- 我可以用std::shared_ptr而不是boost::shared-ptr构建boost库吗
- shared-ptr-C++shared_ptr与unique_ptr用于资源管理