#include <iostream>
#include <memory>
#include <algorithm>
#include <initializer_list>
#include <stdexcept>
using namespace std;
template <class T, class A=allocator<T> >
struct vector_base {
A alloc;
T* elem;
T* space;
T* last;
vector_base(const A& a,typename A::size_type n)
:alloc{a}, elem{alloc.allocate(n)}, space{elem+n}, last{elem+n} {}
~vector_base() {alloc.deallocate(elem, last-elem);}
vector_base(const vector_base&) = delete;
vector_base& operator=(const vector_base&) = delete;
vector_base(const vector_base&& a);
vector_base& operator=(const vector_base&& a);
};
template <class T, class A>
vector_base<T,A>::vector_base(const vector_base&& a)
:alloc{a.alloc},elem{a.elem},space{a.space},last{a.space}
{
a.elem = a.space = a.last = nullptr;
}
template <class T, class A>
vector_base<T,A>& vector_base<T,A>::operator=(const vector_base&& a)
{
swap(*this, a);
return *this;
}
template <class T, class A=allocator<T> >
class Vector {
public:
using size_type = unsigned int;
explicit Vector(size_type n,const T& val=T(),const A& a=A());
explicit Vector(initializer_list<T> lst, const A& a=A());
Vector(const Vector& a);
Vector& operator=(const Vector& a);
Vector(Vector&& a);
Vector& operator=(Vector&& a);
~Vector() {delete_elements();}
size_type size() const {return vb.space-vb.elem;}
size_type capacity() const {return vb.last-vb.elem;}
void reserve(size_type newalloc);
void resize(size_type newsize, const T& val=T());
void clear() {resize(0);}
void push_back(const T& val);
T* begin() {return vb.elem;}
const T* begin() const {vb.elem;}
T* end() {return vb.space;}
const T* end() const {return vb.space;}
T& operator[](size_type p);
private:
void delete_elements();
private:
vector_base<T,A> vb;
};
template <class T, class A>
void Vector<T,A>::delete_elements()
{
for(T* p=begin(); p!=end(); p++)
p->~T();
vb.space = vb.elem;
}
template <class T, class A>
Vector<T,A>::Vector(size_type n,const T& val,const A& a):vb{a,n}
{
uninitialized_fill(begin(), end(), val);
}
template <class T, class A>
Vector<T,A>::Vector(initializer_list<T> lst, const A& a):vb{a, lst.size()}
{
uninitialized_copy(lst.begin(), lst.end(), begin());
}
template <class T, class A>
Vector<T,A>::Vector(const Vector& a):vb{a.vb.alloc, a.size()}
{
uninitialized_copy(a.begin(), a.end(), begin());
}
template <class T, class A>
Vector<T,A>& Vector<T,A>::operator=(const Vector& a)
{
if (capacity() < a.size())
{
Vector<T,A> temp{a};
swap(*this, temp);
return *this;
}
if (*this == a) return *this;
size_type asz = a.size();
size_type sz = size();
if (asz < sz)
{
copy(a.begin(), a.end(), begin());
for(T* p=begin()+asz; p!=end(); p++)
p->~T();
}else {
copy(a.begin(), a.begin()+sz, begin());
uninitialized_copy(a.begin()+sz, a.end(), end());
}
vb.space = vb.elem + asz;
return *this;
}
template <class T, class A>
Vector<T,A>::Vector(Vector&& a):vb{std::move(a.vb)}
{
}
template <class T, class A>
Vector<T,A>& Vector<T,A>::operator=(Vector&& a)
{
clear(); //销毁对象
swap(*this ,a);
return *this;
}
template <class T, class A>
void Vector<T,A>::reserve(size_type newalloc)
{
if (newalloc <=capacity()) return;
vector_base<T,A> b{vb.alloc, newalloc};
for(T* p=begin(), oo=b.elem; p!=end(); p++,oo++)
{
new (static_cast<void*>(&*oo)) T(move(*p));
p->~T();
}
//调整size
b.space = b.elem + size();
swap(vb, b);
}
template <class T, class A>
void Vector<T,A>::resize(size_type newsize, const T& val)
{
reserve(newsize);
if (newsize > size())
uninitialized_fill(begin()+size(), begin()+newsize, val);
else {
for(T* p=begin()+newsize; p!=end(); p++)
p->~T();
}
//调整size,capacity无需调整
vb.space = vb.elem + newsize;
}
template <class T, class A>
void Vector<T,A>::push_back(const T& val)
{
if (size() == capacity())
reserve(capacity() ? capacity()*2 : 8);
vb.alloc.construct(vb.elem+size(), val);
vb.space++;
}
template <class T, class A>
T& Vector<T,A>::operator[](size_type p)
{
if (p >= size())
throw out_of_range{"数组越界"};
return vb.elem[p];
}
int main()
{
Vector<int> ivec{1,2,3,4,5};
for(auto i : ivec)
cout << i << endl;
}
感觉很不错,需要多加练习,多加理解。