//熟悉 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(); }
};
*****************************************************/