我有以下问题:我在我的项目中使用自定义池分配器,而且每次我要分配任何带有新位置的对象时,也会隐式地调用析构函数。
以下是源代码:
试验对象:
class Obj {
public:
Obj(const std::string& s) {
std::cout << "Constructor Called" << std::endl;
}
~Obj() {
std::cout << "Destructor Called" << std::endl;
}
};Main:
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之后调用析构函数!有人能解释为什么会发生这种事吗?
发布于 2017-06-01 11:50:59
..。每次我要分配任何带有新位置的对象时,都会隐式地调用该对象的析构函数。
不,对对象也调用析构函数。你只是假设--不正确--被破坏的对象就是你的池中分配的对象。
直观地说,由于您的allocateNew函数将const作为参数,所以某些东西必须存在,这意味着它是在池中分配任何东西之前创建的。
不过,细节上,
Obj *obj1 = allocator::allocateNew(*poolAllocator, Obj("Hello"));威尔:
Obj("Hello")
使用std::string构造函数创建一个新的匿名临时对象,该构造函数将记录您看到的消息allocateNew(Allocator& allocator, const T& t)
将一个const传递到您的allocateNew函数中。return new (...) T(t)
放置-在池中新建另一个对象,使用隐式生成的复制构造函数,它不记录任何内容。如果您想要准确地了解正在发生的事情,请实现日志版本--所有构造函数(和赋值操作符)变体。
如果要避免临时对象+复制,请传递一个T&& t并将构造移动到池中。
发布于 2017-06-01 11:54:01
声明
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()返回时,在控制传递到下一条语句之前,临时语句将被销毁。
在allocateNew()中创建的副本继续存在。
析构函数不会隐式地在new表达式产生的对象上调用。这是暂时的。
发布于 2017-06-01 11:50:04
这是:‘Obj(“Hello”)创建一个临时的,用于复制新放置中的另一个对象。在此之后,通过调用其析构函数来销毁临时数据。
https://stackoverflow.com/questions/44306499
复制相似问题