gpt4 book ai didi

c++ - 每次我使用 placement new 分配时都会隐式调用析构函数

转载 作者:太空狗 更新时间:2023-10-29 23:49:14 29 4
gpt4 key购买 nike

我有以下问题:我在我的项目中使用自定义池分配器,每次我要分配任何具有新位置的对象时,也会隐式调用该对象的析构函数。

这里是源代码:

测试对象:

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

这是 Allocator 的源代码:分配新函数:

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

好像在Pool Allocator中allocate方法return op之后调用了析构函数!谁能解释为什么会这样?

最佳答案

... every time i am going to allocate any object with placement new, the destructor is also called on that object implicitly

不,析构函数也在一个 对象上调用。您只是错误地假设被销毁的对象是您的池中分配的对象。

直觉上,由于您的 allocateNew 函数将 something 的 const ref 作为参数,因此 something 必须存在,这意味着它已被创建在你的池中分配任何东西之前。

虽然详细,

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

将:

  1. Obj("你好")

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

  2. allocateNew(Allocator& 分配器, const T& t)

    将 const ref 传递给该匿名临时变量到您的 allocateNew 函数中。

  3. 返回新的 (...) T(t)

    在你的池中放置新的另一个对象,使用隐式生成的复制构造函数它不记录任何内容

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

  5. 在语句末尾超出范围时销毁匿名临时文件。

如果您想准确了解正在发生的事情,请实现日志记录版本所有 构造函数(和赋值运算符)变体。

如果你想避免临时对象 + 复制,传递一个 T&& t 并移动构造到池中。

关于c++ - 每次我使用 placement new 分配时都会隐式调用析构函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44306499/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com