天天看點

allocator空間配置設定接口類實作Vector

//熟悉 static: allocate、deallocate 故模闆類allocator對象需要靜态聲明

// construct、destroy(c++17廢棄)

//後期: 學習真正的 内部實作 Alloc模闆類 二級空間配置設定器

//allocator 簡單實作自定義Vector模版
//熟悉 static: allocate、deallocate    故模闆類allocator對象需要靜态聲明
//     construct、destroy(c++17廢棄)
//後期: 學習真正的 内部實作 Alloc模闆類  二級空間配置設定器


#include <iostream>
#include <memory>
using std::cout;
using std::endl;

template <typename T>
class Vector{
public:
    Vector();
    ~Vector();
    void push_back(const T &);
    void pop_back();
    void clear();
    const T &operator[] (int idx) const;
    int size() const{
        return _firstFree - _elems;
    }
    int capacity() const{
        return _end - _elems;
    }

private:
    void reallocate();   //push_back時檢測 size() == capacity()?

private:
    static std::allocator<T> _alloc;   //空間配置設定接口層的靜态對象
    T * _elems;
    T * _firstFree;
    T * _end;
};

template <typename T>
Vector<T>::Vector()
:_elems()
,_firstFree()
,_end(){
    cout << "Vector() ok" <<endl;
}

template <typename T>
Vector<T>::~Vector(){
    if(_elems){
        while(_elems != _firstFree)
            _alloc.destroy(--_firstFree);   
        _alloc.deallocate(_elems,capacity());
    }
    cout<< "~Vector() ok"<<endl;
}

template <typename T>
void Vector<T>::push_back(const T & value){
    if( size() == capacity() )
        reallocate();
    _alloc.construct(_firstFree++ , value);     //元素的添加 實際調用定位表達式new((void*)Pointer)T(value)
}

template <typename T>
void Vector<T>::pop_back(){
    if(size()>){
        _alloc.destroy(--_firstFree);
    }
}

template <typename T>
const T & Vector<T>::operator[] (int idx) const {
    return _elems[idx];
}

template <typename T>
void Vector<T>::reallocate(){
    int oldcapacity = capacity();
    int newcapacity = (oldcapacity ==  ?  : oldcapacity * );
    //1.配置設定新空間
    T * newelems = _alloc.allocate(newcapacity);
    if(_elems){
        //2.原始空間  uninitialized_copy( InputIt first, InputIt last, ForwardIt d_first );
        std::uninitialized_copy(_elems,_firstFree,newelems);
        //3.銷毀原空間對象
        while(_elems != _firstFree)
            _alloc.destroy( --_firstFree);
        //4.銷毀原空間
        _alloc.deallocate(_elems,oldcapacity);
    }
    //5.更新為新空間   在if語句外側
    _elems = newelems;
    _firstFree = newelems + oldcapacity;
    _end = newelems + newcapacity;

}

template <typename T>
void Vector<T>::clear(){
    while(_elems != _firstFree)
        _alloc.destroy(--_firstFree);
    _alloc.deallocate(_elems,capacity());
    cout<< "clear ok"<<endl;
}


template <typename T>
std::allocator<T> Vector<T>:: _alloc;    //static 對象類外初始化

void display(const Vector<int> & vec)
{
    cout << "vec's size = " << vec.size() << endl;
    cout << "vec's capa = " << vec.capacity() << endl;
}

void print(const Vector<int> & vec)
{
    for(int idx = ; idx < vec.size(); ++idx)
    {
        cout << vec[idx] << " ";
    }
}

int main(void)
{
    Vector<int> vec;
    //*******************************size() capacity()測試
    display(vec);
    vec.push_back();
    display(vec);
    vec.push_back();
    display(vec);
    vec.push_back();
    display(vec);
    vec.push_back();
    display(vec);
    vec.push_back();
    display(vec);
    vec.push_back();
    display(vec);
    vec.push_back();
    display(vec);
    cout << endl;
    print(vec);
    cout << endl;
    //
    return ;
}

/*
    Vector模型
     ______________________________
    |_|_|_|_|_|____________________|
     ↑         ↑                    ↑
   _elems   _first_free            _end


    T * _elems;      //指向數組中的第一個元素
    T * _first_free; //指向最後一個實際元素之後的那個元素
    T * _end;        //指向數組本身之後的位置
*/


/*******************************************************allocator stl源碼
STL空間配置設定接口層 —— 模闆類allocator —— 定義

    1. 注:_Tp* allocate(size_type __n)     void deallocate(pointer __p, size_type __n) 是實作層alloc的靜态成員函數
        故模闆類allocator對象需要靜态聲明

    2. typedef alloc _Alloc;   alloc類是空間配置設定的實作


template <class _Tp>
class allocator {
  typedef alloc _Alloc;          // The underlying allocator.
public:
  typedef size_t     size_type;
  typedef ptrdiff_t  difference_type;
  typedef _Tp*       pointer;
  typedef const _Tp* const_pointer;
  typedef _Tp&       reference;
  typedef const _Tp& const_reference;
  typedef _Tp        value_type;

  template <class _Tp1> struct rebind {
    typedef allocator<_Tp1> other;
  };

  allocator() __STL_NOTHROW {}
  allocator(const allocator&) __STL_NOTHROW {}
  template <class _Tp1> allocator(const allocator<_Tp1>&) __STL_NOTHROW {}
  ~allocator() __STL_NOTHROW {}

  pointer address(reference __x) const { return &__x; }
  const_pointer address(const_reference __x) const { return &__x; }

  // __n is permitted to be 0.  The C++ standard says nothing about what
  // the return value is when __n == 0.
  _Tp* allocate(size_type __n, const void* = 0) {
    return __n != 0 ? static_cast<_Tp*>(_Alloc::allocate(__n * sizeof(_Tp))) 
                    : 0;
  }

  // __p is not permitted to be a null pointer.
  void deallocate(pointer __p, size_type __n)
    { _Alloc::deallocate(__p, __n * sizeof(_Tp)); }

  size_type max_size() const __STL_NOTHROW 
    { return size_t(-1) / sizeof(_Tp); }

  void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); }
  void destroy(pointer __p) { __p->~_Tp(); }
};
*****************************************************/
           

繼續閱讀