C ++ Vector实现分配新对象

时间:2016-10-14 17:14:28

标签: c++ class memory memory-management vector

我差不多完成了std :: vector类型的vector的实现(希望如此),但是我在代码中遇到了一些小错误,而我似乎无法找到位置。基本上当我构建Vector并使用push_back时,向量会自动为更多元素(特别是向量大小的两倍)分配新内存,但是当这样做时,"额外空间"被初始化为0,我不知道为什么。

这是我的代码:

Vector.h

#include <memory>
#include <cstddef>

template <class T>
class Vec{
    public:
        typedef T* iterator;
        typedef const T* const_iterator;
        typedef size_t size_type;
        typedef T value_type;

        Vec(){create();}
        Vec(size_type n, const T& val = T()) {create(n, val);}

        ~Vec() {uncreate();}

        //copy constructor
        Vec(const Vec& v) {create(v.begin(), v.end());}
        //assignment operator
        Vec& operator=(const Vec&);

        size_type size() const {return limit - data;}

        //index operators
        T& operator[](size_type i) {return data[i];}
        const T& operator[](size_type i) const {return data[i];}

        iterator begin() {return data;}
        const_iterator begin() const {return data;}

        iterator end() {return limit;}
        const_iterator end() const {return limit;}

        void push_back(const T&);


    private:
        iterator data; //1st element
        iterator avail; //one past last constructed element
        iterator limit; //one past last available element

        //Memory management
        std::allocator<T> alloc;

        void create();
        void create(size_type, const T&);
        void create(const_iterator, const_iterator);

        void uncreate();

        void grow();
        void unchecked_append(const T&);

};

template <class T>
void Vec<T>::push_back(const T& val){
    if(avail == limit)
        grow();
    unchecked_append(val);
}

template <class T>
Vec<T>& Vec<T>::operator=(const Vec& rhs){
    //self-assign
    if(&rhs != this){
        uncreate;
        create(rhs.begin(), rhs.end());
    }
    return *this;
}

// Empty Vector, pointers to 0
template <class T> void Vec<T>::create(){
    data = avail = limit = 0;
}

// Allocate memory for (size)
template <class T> void Vec<T>::create(size_type n, const T& val){
    data = alloc.allocate(n); // returns pointer to first element
    limit = avail = data +n;
    std::uninitialized_fill(data, limit, val);
}

template <class T> void Vec<T>::create(const_iterator i, const_iterator j){
    data = alloc.allocate(j-i);
    limit = avail =std::uninitialized_copy(i, j, data);
}

template <class T> void Vec<T>::uncreate(){
    if(data){
        iterator it = avail;
        while(it != data)
            alloc.destroy(--it);

        // Free space
        alloc.deallocate(data, limit - data);
    }
    // Empty Vector
    data = limit = avail = 0;
}

template <class T> void Vec<T>::grow(){
    // Allocate twice the space we had
    size_type new_size = std::max(2 * (limit - data), ptrdiff_t(1));

    // Allocate new space and copy to new space
    iterator new_data = alloc.allocate(new_size);
    iterator new_avail = std::uninitialized_copy(data, avail, new_data);

    // Return old space used
    uncreate();

    // Reset pointers to point to new space
    data = new_data;
    avail = new_avail;
    limit = data + new_size;
}

template <class T> void Vec<T>::unchecked_append(const T& val){
    alloc.construct(avail++, val);
}

这就是我创建矢量的方式

的main.cpp

#include "vector.h"
#incude <iostream>

using namespace std;

int main(){
    Vec<int> v1;
    v1.push_back(12);
    v1.push_back(9);
    v1.push_back(74);
    v1.push_back(22);
    Vec<int> v2 = v1;  
    v2.push_back(70); //After doing this the vector is (12, 9, 74, 22, 70, 0, 0, 0)
    for(auto e: v2) cout << e << " ";
    cout << endl;
}

感谢您提供任何帮助,并且对实际代码的任何反馈都表示赞赏。 :)

1 个答案:

答案 0 :(得分:1)

问题是(我不知道这是否真的有问题)

template <class T> void Vec<T>::grow(){
    // Allocate twice the space we had
    size_type new_size = std::max(2 * (limit - data), ptrdiff_t(1));
....
....
}

无需进行任何矢量复制即可重现您的问题。

插入第5个元素后,即使在第一个向量中也可以看到问题

    v1.push_back(12);
    v1.push_back(9);
    v1.push_back(74);
    v1.push_back(22);
    v1.push_back(22);  //5th elemnt.

现在打印尺寸;

cout<<v1.size()<<endl; - it says 8.

即使是std向量,在resize()之后,为空元素打印零也是正常的行为。

看看这个例子: http://en.cppreference.com/w/cpp/container/vector/resize

如果您不想要额外的零,则必须调整“:new_size”计算。