首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >每次配置新位置时都会隐式调用析构函数。

每次配置新位置时都会隐式调用析构函数。
EN

Stack Overflow用户
提问于 2017-06-01 11:38:46
回答 3查看 88关注 0票数 2

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

以下是源代码:

试验对象:

代码语言:javascript
复制
class Obj {
public:
    Obj(const std::string& s) {  
        std::cout << "Constructor Called" << std::endl; 
    }
    ~Obj() { 
        std::cout << "Destructor Called" << std::endl; 
    }

};

Main:

代码语言:javascript
复制
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函数:

代码语言:javascript
复制
template <class T> T* allocateNew(Allocator& allocator, const T& t)
{
        return new (allocator.allocate(sizeof(T), __alignof(T))) T(t);
}

池分配器:

代码语言:javascript
复制
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之后调用析构函数!有人能解释为什么会发生这种事吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-06-01 11:50:59

..。每次我要分配任何带有新位置的对象时,都会隐式地调用该对象的析构函数。

不,对对象也调用析构函数。你只是假设--不正确--被破坏的对象就是你的池中分配的对象。

直观地说,由于您的allocateNew函数将const作为参数,所以某些东西必须存在,这意味着它是在池中分配任何东西之前创建的。

不过,细节上,

代码语言:javascript
复制
Obj *obj1 = allocator::allocateNew(*poolAllocator, Obj("Hello"));

威尔:

  1. Obj("Hello") 使用std::string构造函数创建一个新的匿名临时对象,该构造函数将记录您看到的消息
  2. allocateNew(Allocator& allocator, const T& t) 将一个const传递到您的allocateNew函数中。
  3. return new (...) T(t) 放置-在池中新建另一个对象,使用隐式生成的复制构造函数,它不记录任何内容。
  4. 返回指向在池中分配的新对象的指针。
  5. 当匿名临时语句在语句结束时超出作用域时,销毁它。

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

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

票数 5
EN

Stack Overflow用户

发布于 2017-06-01 11:54:01

声明

代码语言:javascript
复制
Obj *obj1 = allocator::allocateNew(*poolAllocator, Obj("Hello"));

创建Obj类型的临时(从Obj("Hello")),并通过引用传递给allocator::allocateNew()

在职能范围内

代码语言:javascript
复制
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表达式产生的对象上调用。这是暂时的。

票数 2
EN

Stack Overflow用户

发布于 2017-06-01 11:50:04

这是:‘Obj(“Hello”)创建一个临时的,用于复制新放置中的另一个对象。在此之后,通过调用其析构函数来销毁临时数据。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44306499

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档