ZSL_Vector

最近事情太多了,是在没时间更新,刚好最近也在读标准库源码,其实开始已经写过自己的string类,但是发现和标准库相差甚远,所以会重新写一下,这次花了两个小时不到模仿了标准库的vector,可能内部实现方式有点点不一样,因为标准库是把对象构造和析构,空间的配置和销毁是分开的,因为我看的SGI的STL,空间配置器那部分涉及太多内存操作,包括内存池等,这都是需要很深厚的功力才能完成,学生狗一只就不准备模仿了。

这次的代码,主要参考了:cppreference,SGI STL2.9版本,STL源码剖析书。

注:暂时只测试了一部分,后续会慢慢更新

—————————————————————————————————————————

#ifndef __ZSL_Vector_H__
#define __ZSL_Vector_H__

#include <iostream>
#include <algorithm>
using namespace std;

template<typename T>
class ZSL_Vector
{
public:
    using value_type        = T;
    using pointer           = value_type*;
    using const_pointer     = const value_type*;
    using iterator          = value_type*;
    using const_iterator    = const value_type*;
    using reference         = value_type&;
    using const_reference   = const value_type&;
    using size_type         = size_t;
    using difference_type   = ptrdiff_t;

private:
    iterator start;
    iterator finish;
    iterator end_of_storage;

private:
    pointer allocate(size_t n) { return (pointer)malloc(n * sizeof(T)); }
    void construct(pointer p, const value_type& value) { new(p)value_type(value); }
    void destroy_aux(pointer p) { p->~T(); }
    void destroy(pointer first, pointer last) {
        while(first != last){
            destroy_aux(first);
            ++first;
        }
    }
    void deallocate() { if(start) free(start); }
    iterator uninitialized_copy(iterator first, iterator last, iterator res){
        while(first < last){
            construct(res, *first);
            ++first;
            ++res;
        }
        return res + (last - first);
    }

    iterator copy(iterator first, iterator last, iterator res){
        while(first < last){
            *res = *first;
            ++first, ++res;
        }
        return res + (last - first);
    }

    void uninitialized_fill(size_t n, const T& value){
        start = allocate(n);
        finish = start + n;
        for(int i = 0; i < n; ++i)
            construct(start + i, value);
        end_of_storage = finish;
    }

    void fill(iterator first, iterator last, const value_type& value){
        while(first != last){
            *first = value;
            ++first;
        }
    }

    void refill(const ZSL_Vector<T>& rhs){
        start = allocate(rhs.size());
        uninitialized_copy(rhs.start, rhs.finish, start);
        finish = start + rhs.size();
        end_of_storage = finish;
    }

    void copy_backward(iterator first, iterator last, iterator it){
        while(last != first){
            *it = *last;
            --last;
            --it;
        }
    }

    void insert_aux(iterator pos, const T& value);
    void erase_aux1(iterator pos);
    void erase_aux2(iterator pos1, iterator pos2){
        iterator new_finish = uninitialized_copy(pos2, finish, pos1);
        destroy(new_finish, finish);
        finish = new_finish;
    }

public:
    ZSL_Vector() : start(0), finish(0), end_of_storage(0) {}
    ZSL_Vector(size_t n, const T& value) { uninitialized_fill(n, value); }
    ZSL_Vector(size_t n) { uninitialized_fill(n, T()); }
    ZSL_Vector(const T& value) { uninitialized_fill(1, value); }
    ZSL_Vector(iterator first, iterator last){
        auto ptr = first;
        for(; first != last; ++first)
            push_back(*first);
    }
    ZSL_Vector(const ZSL_Vector<T> &rhs){ refill(rhs); }

    ZSL_Vector<T>& operator = (const ZSL_Vector<T> &rhs){
        if(this != &rhs){
            if(rhs.size() > capacity()){
                iterator new_start = allocate(rhs.size());
                uninitialized_copy(rhs.cbegin(), rhs.cend(), new_start);
                destroy(start, finish);
                deallocate();
                start = new_start;
                end_of_storage = finish;
            }
            else if(size() >= rhs.size()){
                iterator tmp = copy(rhs.begin(), rhs.end(), begin());
                destroy(tmp, finish);
            }
            else{

            }
            finish = start + rhs.size();
        }
        return *this;
    }
    ~ZSL_Vector(){
        destroy(start, finish);
        deallocate();
    }

    void assign( size_type count, const T& value ){
        if(count <= size()){
            erase(end() - count, end());
            finish -= count;
            fill(begin(), end(), value);
        }
        else if(count <= capacity()){
            finish += count;
            fill(begin(), end(), value);
        }
        else{
            fill(begin(), end(), value);
            insert(end(), count, value);
        }
    }
    void assign(initializer_list<T> ilist){
        size_type len = ilist.size();
        if(len <= size()){
            erase(end() - len, end());
            finish -= len;
            copy(ilist.begin(), ilist.end(), begin());
        }
        else if(len <= capacity()){
            copy(ilist.begin(), ilist.begin() + size(), begin());
            finish = uninitialized_copy(ilist.begin() + size(), ilist.end(), finish);
        }
        else{
            copy(ilist.begin(), ilist.begin() + size(), begin());
            insert(end(), ilist.begin() + size(), ilist.end());
        }
    }

    reference at(size_type pos){
        if(pos >= size())
            throw "out_of_range";
        return *(start + pos);
    }
    const_reference at(size_type pos) const {
        return const_cast<reference>(static_cast<ZSL_Vector<T>>(*this).start[pos]);
    }
    reference operator[](size_type pos){ return *(start + pos); }
    const_reference operator[](size_type pos) const { return *(start + pos); }

    reference front() { return *begin(); }
    const_reference front() const { return *begin(); }
    reference back() { return *(end() - 1); }
    const_reference back() const { return *(end() - 1); }

    iterator begin() { return start; }
    const_iterator cbegin() const { return start; }
    iterator end() { return finish; }
    const_iterator cend() const { return finish; }

    bool empty() const { return finish == 0; }
    size_type size() const { return finish - start; }
    size_type max_size() const { return size_type(-1)/sizeof(value_type); }
    pointer data() noexcept { return (pointer)start; }
    const_pointer data() const noexcept { return (const_pointer)start; }

    void reserve(size_type n){
        if (n < size())
            erase(begin() + n, end());
        else
            insert(end(), n, T());
    }

    size_type capacity() const { return end_of_storage - start; }

    void clear(){
        erase(begin(), end());
    }

    iterator insert(iterator pos, const T& value){
        size_type n = pos - begin();
        if(finish != end_of_storage && pos == end()){
            construct(finish, value);
            ++finish;
        }
        else
            insert_aux(pos, value);
        return begin() + n;
    }
    iterator insert(const_iterator pos, const T& value){
        size_type n = pos - begin();
        if(finish != end_of_storage && pos == end()){
            construct(finish, value);
            ++finish;
        }
        else
            insert_aux(pos, value);
        return begin() + n;
    }

    iterator insert( const_iterator pos, T&& value ){ insert(pos, value); }

    void insert( iterator pos, size_type count, const T& value );

    /*
    iterator insert( const_iterator pos, size_type count, const T& value );
    template< class InputIt >
    void insert( iterator pos, InputIt first, InputIt last);
    template< class InputIt >
    iterator insert( const_iterator pos, InputIt first, InputIt last );
    iterator insert( const_iterator pos, std::initializer_list<T> ilist );
    */
    iterator erase(iterator pos){
        if(pos + 1 != end())
            copy(pos + 1, end(), pos);
        --finish;
        destroy_aux(finish);
        return pos;
    }
    iterator erase(const_iterator pos){
        if(pos + 1 != end())
            copy(pos + 1, end(), pos);
        --finish;
        destroy_aux(finish);
        return pos;
    }
    iterator erase(iterator first, iterator last){
        iterator tmp = copy(last, finish, first);
        destroy(tmp, finish);
        finish = finish - (last - first);
        return first;
    }
    iterator erase(const_iterator first, const_iterator last){
        iterator tmp = copy(last, finish, first);
        destroy(tmp, finish);
        finish = finish - (last - first);
        return first;
    }

    void push_back(const T& value) {
        if(finish != end_of_storage){
            construct(finish, value);
            ++finish;
        }
        else
            insert_aux(end(), value);
    }

    void pop_back() {
        --finish;
        destroy_aux(finish);
    }

    void swap(ZSL_Vector& other){
        using std::swap;
        swap(start, other.start);
        swap(finish, other.finish);
        swap(end_of_storage, other.end_of_storage);
    }
};

template<typename T>
bool operator == (const ZSL_Vector<T>& lhs, const ZSL_Vector<T>& rhs)
{
    for(auto i = lhs.cbegin(), j = rhs.cbegin(); i != lhs.cend() && j != rhs.cend(); ++i, ++j)
        if(*i != *j)
            return false;
    return lhs.size() == rhs.size();
}

template<typename T>
bool operator != (const ZSL_Vector<T>& lhs, const ZSL_Vector<T>& rhs)
{
    return !(lhs == rhs);
}

template<typename T>
bool operator < (const ZSL_Vector<T>& lhs, const ZSL_Vector<T>& rhs)
{
    for(auto i = lhs.cbegin(), j = rhs.cbegin(); i != lhs.cend() && j != rhs.cend(); ++i, ++j)
        if(*i >= *j)
            return false;
    return lhs.size() < rhs.size();
}

template<typename T>
bool operator <= (const ZSL_Vector<T>& lhs, const ZSL_Vector<T>& rhs)
{
    for(auto i = lhs.cbegin(), j = rhs.cbegin(); i != lhs.cend() && j != rhs.cend(); ++i, ++j)
    if(*i > *j)
        return false;
    return lhs.size() < rhs.size();
}

template<typename T>
bool operator > (const ZSL_Vector<T>& lhs, const ZSL_Vector<T>& rhs)
{
    return !(lhs <= rhs);
}

template<typename T>
bool operator >= (const ZSL_Vector<T>& lhs, const ZSL_Vector<T>& rhs)
{
    return !(lhs < rhs);
}

template<typename T>
void ZSL_Vector<T>::insert_aux(iterator pos, const T& value)
{
    if(finish != end_of_storage){
        construct(finish, *(finish - 1));
        ++finish;
        copy_backward(pos, finish - 2, finish - 1);
        *pos = value;
    }
    else{
        const size_type old_size = size();
        const size_type len = old_size == 0 ? 1 : (2 * old_size);
        iterator new_start = allocate(len);
        iterator new_finish = new_start;
        new_finish = uninitialized_copy(begin(), pos, new_finish);
        construct(new_finish, value);
        ++new_finish;
        new_finish = uninitialized_copy(pos, end(), new_finish);
        destroy(begin(), end());
        deallocate();
        start = new_start;
        finish = new_finish;
        end_of_storage = start + len;
    }
}

template<typename T>
void ZSL_Vector<T>::insert( iterator pos, size_type count, const T& value ){
    if(count != 0){
        if(end_of_storage - finish >= count){
            const size_type elems_after = finish - pos;
            iterator old_finish = finish;
            if(elems_after > count){
                uninitialized_copy(finish - count, finish, finish);
                finish += count;
                copy_backward(pos, old_finish - count, old_finish);
                fill(pos, pos + count, value);
            }
            else{
                size_type len = count - elems_after;
                while(len--){
                    *finish = value;
                    ++finish;
                }
                uninitialized_copy(pos, pos + count, finish);
                finish += elems_after;
                fill(pos, pos + count, value);
            }
        }
        else{
            const size_type old_size = size();
            const size_type len = old_size + std::max(old_size, count);
            iterator new_start = allocate(len);
            iterator new_finish = new_start;
            new_finish = uninitialized_copy(start, pos, new_start);
            while(count--){
                *new_finish = value;
                ++new_finish;
            }
            new_finish = uninitialized_copy(pos, finish, new_finish);
            destroy(start, finish);
            deallocate();
            start = new_start;
            finish = new_finish;
            end_of_storage = new_start + len;
        }
    }
}


#endif //!__ZSL_Vector_H__

 

posted @ 2017-11-01 18:56  CoderZSL  阅读(170)  评论(0编辑  收藏  举报