【发布时间】:2017-01-31 14:49:15
【问题描述】:
上下文:
我正在尝试创建一个自定义分配器,它在某些方面模仿 std::allocator(不是派生自),但允许实例化分配器。我的通用容器有构造函数,允许用户指定一个指向自定义Allocator 对象的指针。当没有指定分配器时,我希望它默认为从抽象 Allocator 类派生的单例 NewDeleteAllocator。这只是包装了全局 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 ) 如何知道ptr 指向的数据的大小?这是一个安全的操作吗?据我了解,根据 C++ 标准,通过 void 指针删除可能会导致未定义的行为。如果这很糟糕,我还能如何实现呢?
更多详情:
我用以下代码做了一些非常粗略的初步测试:
// inside member function of 'FooContainer'
for( size_t i = 0; i < 1000000; i++ )
{
for( size_t j; j = 1; j < 20; j++ )
{
void * ptr = allocator->allocate( j );
allocator->deallocate( ptr );
}
}
我使用 Xcode 的分析工具观察了程序的总内存使用情况。内存使用量保持在一个较低的值。我知道这不是检查内存泄漏的正确方法。我不知道编译器是否可以优化它。我只是在试验这个想法。在我对我的图书馆的架构做出任何承诺之前,我非常感谢对主要问题的一些投入。首先,整个方法可能存在缺陷。
感谢您的意见。我不想做任何不好的假设。
【问题讨论】:
标签: c++ c++11 memory-management stl allocator