上下文
我正在尝试创建一个自定义分配器,它在某些方面模仿std::allocator
(非衍生自),但允许实例化分配器。我的通用容器具有构造函数,允许用户指定自定义Allocator
对象的指针。如果未指定allocator,我希望它默认为从抽象NewDeleteAllocator
类派生的单Allocator
。这简单地包含了全局new
和delete
运算符。这个想法来自Pablo Halpern的Towards a Better Allocator Model。
使用自定义分配器的客户端代码:
// 'foo_container.hpp'
// enclosed in package namespace
template <class T>
class FooContainer
{
private:
// -- Private member properties --
Allocator * allocator;
public:
// -- Constructors --
FooContainer( Allocator * allocator = 0 )
{
this->allocator = !allocator ? (Allocator *)defaultAllocator : allocator;
}
FooContainer( const FooContainer &rhs, Allocator * allocator = 0 )
{
// don't implicitly copy allocator
this->allocator = !allocator ? (Allocator *)defaultAllocator : allocator;
// copying logic goes here
}
}
自定义分配器实施:
// 'allocator.hpp'
// enclosed in package namespace
class Allocator
{
public:
virtual ~Allocator(){ };
virtual void * allocate( size_t bytes ) = 0;
virtual void deallocate( void * ptr ) = 0;
};
class NewDeleteAllocator : public Allocator
{
public:
virtual ~NewDeleteAllocator()
{
}
virtual void * allocate( size_t bytes )
{
return ::operator new( bytes );
}
virtual void deallocate( void * ptr )
{
::operator delete( ptr ); // memory leak?
}
private:
};
//! @todo Only for testing purposes
const Allocator * defaultAllocator = new NewDeleteAllocator();
主要问题:
我知道通过new
分配也可能会存储有关分配的信息以及指针。我意识到使用范围解析运算符delete
调用::
与调用delete
并不完全相同,但::delete( ptr )
如何知道{{1}的数据大小指向?这是安全的操作吗?根据我的理解,根据C ++标准,通过void指针删除可能会导致未定义的行为。如果这很糟糕,我还能怎样实现这个呢?
更多详情:
我使用以下代码做了一些非常粗略的初步测试:
ptr
我使用Xcode的分析工具观察了程序的总内存使用情况。内存使用率保持不变为低值。我知道这不是检查内存泄漏的正确方法。我不知道编译器是否可以优化它。我只是试验这个想法。在对图书馆的架构做出任何承诺之前,我真的很感激主要问题的一些输入。整个方法可能首先存在缺陷。
感谢您的投入。我不想做出任何错误的假设。
答案 0 :(得分:1)
对从::delete
的调用返回的指针调用::new
是安全的。
通过调用::delete[]
返回的指针调用::new[]
是安全的。
如果您不打算使用x类型,则通过拨打delete x
时返回的指针调用auto x = new {...}
是安全的。
如果您不打算使用x类型,则通过拨打delete[] x
时返回的指针调用auto x = new {...}[z]
是安全的。
混合是UB
&#34;但是:: delete(ptr)如何知道ptr所在数据的大小 指向&#34;
C ++中的动态分配内存通常通过堆实现。堆最初分配了大量的空间,而不是处理它,让程序处理它的随机块。堆存储它分配的每个内存块的大小。例如,如果您需要8个字节的内存,则堆保留至少12个字节,保持前4个字节的大小和后者的8个数据。然后,它返回一个指向8个字节的指针。因此,在删除过程中,程序知道要删除多少&#34;&#34;通过访问指针 - 4。