2017-06-01 38 views
2

我有以下问题:我使用我的项目自定义池Allocator,并且每次我要分配任何对象与位置新,析构函数也被称为隐含的对象。析构函数隐式调用,每次我分配放置新

这里是源代码:

测试对象:

class Obj { 
public: 
    Obj(const std::string& s) { 
     std::cout << "Constructor Called" << std::endl; 
    } 
    ~Obj() { 
     std::cout << "Destructor Called" << std::endl; 
    } 

}; 

主营:

int main() 
{ 

    void *pmemory; 
    pmemory = malloc(ONEGIG_SIZE); 

    PoolAllocator* poolAllocator = new PoolAllocator(sizeof(Obj), __alignof(Obj), ONEGIG_SIZE, pmemory); 
    Obj *obj1 = allocator::allocateNew(*poolAllocator, Obj("Hello")); //<-- const and dest is called 

    //...... 

    return 0; 
} 

这里是分配器的源代码: AllocateNew功能:

template <class T> T* allocateNew(Allocator& allocator, const T& t) 
{ 
     return new (allocator.allocate(sizeof(T), __alignof(T))) T(t); 
} 

池分配器:

PoolAllocator::PoolAllocator(size_t objectSize, u8 objectAlignment, size_t size, void* mem) 
     : Allocator(size, mem), _objectSize(objectSize), _objectAlignment(objectAlignment) 
{ 
    ASSERT(objectSize >= sizeof(void*)); 

    //Calculate adjustment needed to keep object correctly aligned 
    u8 adjustment = pointer_math::alignForwardAdjustment(mem, objectAlignment); 

    _free_list = (void**)pointer_math::add(mem, adjustment); 

    size_t numObjects = (size-adjustment)/objectSize; 

    void** p = _free_list; 

    //Initialize free blocks list 
    for(size_t i = 0; i < numObjects-1; i++) 
    { 
     *p = pointer_math::add(p, objectSize); 
     p = (void**) *p; 
    } 

    *p = nullptr; 
} 

PoolAllocator::~PoolAllocator() 
{ 
    _free_list = nullptr; 
} 

void* PoolAllocator::allocate(size_t size, u8 alignment) 
{ 
    ASSERT(size == _objectSize && alignment == _objectAlignment); 

    if(_free_list == nullptr) 
     return nullptr; 

    void* p = _free_list; 

    _free_list = (void**)(*_free_list); 

    _used_memory += size; 
    _num_allocations++; 

    return p; 
} 

void PoolAllocator::deallocate(void* p) 
{ 
    *((void**)p) = _free_list; 

    _free_list = (void**)p; 

    _used_memory -= _objectSize; 
    _num_allocations--; 
} 

似乎在回复O P上之后在池分配器分配方法调用析构函数!任何人都可以解释为什么会发生?

+1

我想说你应该添加调试打印* *所有*构造函数。有些东西告诉我,你看到的额外的析构函数实际上发生在一个临时任务上,可能在这里:'Obj * obj1 = allocator :: allocateNew(* poolAllocator,Obj(“Hello”));'。 – HolyBlackCat

回答

5

... ...每一个我要去分配与安置任何新对象时,析构函数也被称为该对象隐含

没有,析构函数还呼吁一个对象。你只是假设 - 错误地说 - 被销毁的对象是你池中分配的对象。

直观的,因为你的allocateNew函数参数类型为const裁判东西作为一个参数,即东西必须存在,这意味着任何东西之前在池中被分配创建它。

在虽然详细,

Obj *obj1 = allocator::allocateNew(*poolAllocator, Obj("Hello")); 

将:

  1. Obj("Hello")

    创建一个新的匿名临时对象,与std::string构造函数将记录你看到

  2. 消息
  3. allocateNew(Allocator& allocator, const T& t)

    将一个const引用传递给那个匿名临时函数到你的allocateNew函数中。

  4. return new (...) T(t)

    投放新另一个对象在池中,采用隐式生成的拷贝构造函数不记录任何

  5. 返回一个指向分配的新对象的池

  6. 当它在语句结束时超出范围时会销毁匿名临时文件。

如果你想发生了什么的精确图像,实现记录版本所有构造函数(和赋值运算符)的变种。

如果您想避免临时对象+复制,请将T&& t和move-construct传递到池中。

1

This:'Obj(“Hello”)'创建一个临时文件,用于复制初始化新放置的另一个对象。之后,通过调用它的析构函数销毁临时对象。

2

声明

Obj *obj1 = allocator::allocateNew(*poolAllocator, Obj("Hello")); 

创建临时Obj类型(从Obj("Hello"))的,并通过参考allocator::allocateNew()传递给它。

在函数

template <class T> T* allocateNew(Allocator& allocator, const T& t) 
{ 
     return new (allocator.allocate(sizeof(T), __alignof(T))) T(t); 
} 

接收临时对象作为t,并且new (allocator.allocate(sizeof(T), __alignof(T))) T(t)创建其副本(在由allocator.allocate()与所提供的参数中提供的存储器中。这将使用复制构造,其代码不跟踪。

allocator::allocateNew()回报,并控制传递到下一个语句之前,临时被破坏。

的复制c在allocateNew()内部继续存在。

析构函数没有在new表达式导致的对象上隐式调用。它被要求暂时的。