为什么我的C ++ 11分配器的dtor被调用两次?

时间:2018-03-27 16:09:16

标签: c++ c++11 destructor allocator

我编写了自己的基本c ++ 11分配器来分解它,看看它是如何工作的。事情进展顺利,但出于某种原因,我的dtor被叫了两次。这不是现在的问题,但我可以想象一个有状态的分配器在第二次调用dtor时尝试取消引用nullptr的情况,所以我很好奇这是否是预期的行为,如果是,是否有办法避免它?

以下是代码:

#include<iostream>
#include<vector>
#include<new>

using std::vector;
using std::cout;
using std::endl;
using __gnu_cxx::ptrdiff_t;

template<typename elem_t>
struct myAlloc {
    typedef elem_t value_type;
    typedef elem_t * pointer;
    typedef const elem_t * const_pointer;
    typedef elem_t & reference;
    typedef const elem_t & const_reference;
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;
    template<typename other_elem_t>
    struct rebind {
        typedef myAlloc<other_elem_t> other;
    };

    myAlloc() {
        cout << "constructing myAlloc" << endl;
    }
    ~myAlloc() {
        cout << "destructing myAlloc" << endl;
    }
    pointer address(reference x) const {
        cout << "myAlloc retrieving address" << endl;
        return &x;
    }
    const_pointer address(const_reference x) const {
        cout << "myAlloc retrieving address of x" << endl;
        return &x;
    }
    pointer allocate(size_type n, const void * hint = 0) {
        cout << "myAlloc allocating n elem_t's" << endl;
        pointer retval = (pointer)malloc(n * sizeof(value_type));

        if (retval == nullptr)
            throw std::bad_alloc();
        return retval;
    }
    void deallocate(pointer p, size_type n) {
        cout << "myAlloc deallocating n elem_t's" << endl;
        free(p);
    }
    size_type max_size() const throw() {
        return -1;
    }
    void construct(pointer p, const_reference val) {
        cout << "Constructing an elem_t 'val' at address p" << endl;
        new ((void*)p) value_type (val);
    }
    void destroy(pointer p) {
        cout << "Destroying the elem_t at address p" << endl;
        p->~value_type();
    }
};  

void test() {
    cout << "creating vec" << endl;
    vector<int, myAlloc<int> > myvec = {1, 2, 3, 4, 5};
    cout << "done creating vec" << endl;
}   
int main() {
    test();
    cout << "main" << endl;
}

这是输出:

creating vec
constructing myAlloc
myAlloc allocating n elem_t's
Constructing an elem_t 'val' at address p
Constructing an elem_t 'val' at address p
Constructing an elem_t 'val' at address p
Constructing an elem_t 'val' at address p
Constructing an elem_t 'val' at address p
destructing myAlloc
done creating vec
Destroying the elem_t at address p
Destroying the elem_t at address p
Destroying the elem_t at address p
Destroying the elem_t at address p
Destroying the elem_t at address p
myAlloc deallocating n elem_t's
destructing myAlloc  
main

我的猜测是,分配器只要在使用时就在本地构建,并在分配完对象后立即进行破坏。但是,尽管分配器被破坏,我们仍然会调用destroydeallocate函数。为什么这样实现?分配完成后如何破坏分配器有用吗?如何在解除分配后调用成员函数不会破坏一般情况下的事情?

1 个答案:

答案 0 :(得分:0)

答案发表在评论中。分配器构造两次,一次用于分配,一次用于解除分配。谢谢@ T.C.为解决方案和@ivaigult实施