每次我分配新的位置时,都会隐式地称为destuructor

Destructor called implicitly every time I allocate with placement new

本文关键字:destuructor 分配 位置      更新时间:2023-10-16

我有以下问题:我在项目自定义池分配器上使用,每当我将任何对象分配给其他对象时,destructor也会被暗中调用该对象。

这是源代码:

测试对象:

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;
}

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

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之后,驱动器被调用!任何人都可以解释为什么会发生这种情况?

...每当我将任何对象分配给新的对象时,destuructor也会暗中列出该对象

no,在 and 对象上也称驱动器也被调用。您只是假设 - 错误地 - 被摧毁的对象是分配在池中的对象。

直觉上,由于您的allocateNew函数将const ref作为某物作为参数,因此必须存在某物必须存在的参数,这意味着它是在您的池中分配任何内容之前就创建的。

详细说明,

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

Will:

  1. Obj("Hello")

    使用std::string构造函数创建一个新的匿名临时对象,该对象将记录您看到的消息

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

    将const ref转到您的 allocateNew函数中。

  3. return new (...) T(t)

    使用隐式生成的复制构造函数放置新的对象,它不记录任何内容

  4. 将指针返回到池中分配的新对象

  5. 在语句结束时销毁匿名临时性。

如果您想对正在发生的事情进行准确的图片,请实现登录版本 ash all 构造函数(和分配运算符(变体。

如果要避免临时对象 复制,请传递T&& t并将构造移动到池中。

语句

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);
}

接收该临时对象为tnew (allocator.allocate(sizeof(T), __alignof(T))) T(t)创建了它的副本(在allocator.allocate()提供的带有所提供的参数的内存中。这使用了复制构造函数,您的代码未跟踪。

>

allocator::allocateNew()返回,并且在控制传递到下一个语句之前,临时性被摧毁。

allocateNew()中创建的副本继续存在。

new表达式产生的对象上,驱动器不会被隐式称为。它被要求用于临时。

this:'obj(" hello"('创建了一个临时性,用于在新位置中复制另一个对象。之后,暂时通过调用其破坏者。