在C ++中取消分配分配器

时间:2016-12-17 19:19:02

标签: c++ dynamic-memory-allocation dealloc allocator

我已经定义了一个类模板Vec,其中包含一个类似于矢量的T序列:

template <typename T> class Vec {
    public:
        size_t size() const { return first_free - elements; }
        size_t capacity() const { return cap - elements; }
        T *begin() const { return elements; }
        T *end() const { return first_free; }
        void resize(const size_t); // something wrong in this function
        ... 
    private:
        allocator<T> alloc; //allocates the elements
        T *elements; // pointer to the first element in the array
        T *first_free; // pointer to the first free element in the array
        T *cap; // pointer to one past the end of the array
        ...
}; 

当我的代码调用此函数时,程序将崩溃,

template <typename T> void Vec<T>::resize(const size_t newcap)
{
    // this part goes well
    if(newcap > capacity()) {
        auto newdata = alloc.allocate(newcap);
        auto dest = newdata;
        auto orig = elements;
        for(size_t i = 0; i != size(); ++i) 
            alloc.construct(dest++, std::move(*orig++));
        elements = newdata;
        first_free = dest;
        cap = elements + newcap;
    }
    // crash happens in the following two parts
    else if(size() <= newcap && newcap < capacity()) { // deallocate the redundant memory where no element exists
       alloc.deallocate(elements + newcap, capacity() - newcap); // this line causes crash 
       cap = elements + newcap; 
    }   
    else if(size() < newcap) { // destroy the elements and deallocate the memory
        for(auto p = first_free; p != elements + newcap; /*empty*/)
            alloc.destroy(--p);
        alloc.deallocate(elements + newcap, capacity() - newcap); // this line causes crash 
        first_free = cap = elements + newcap;
    }
}

调用代码:

Vec<string> v{"aaa", "bbb", "ccc"}; // size() == 3, capacity == 3
v.resize(2); // to resize v to size() == 2, capacity == 2

我认为我已经做出了正确的deallocate调用和正确的指针算法。谢谢。

1 个答案:

答案 0 :(得分:1)

alloc.deallocate(elements + newcap, capacity() - newcap);

你做不到。分配器全部或全部:您要么取消分配已分配的整个块,要么不管它。

要缩小已分配的内存,请执行与新大小大于当前容量时相同的分配和复制舞蹈,但分配新的较小大小。

顺便提一下,标记为//this part goes well的部分存在一个主要问题:它永远不会释放旧的内存块。