实现
#include<iostream>
#include<string>
#include<assert.h>
#include <cstring>
using namespace std;
struct TrueType
{
};
struct FalseType
{
};
template <class T>
struct IsPoD
{
typedef struct FalseType ispod;
};
template<>
struct IsPoD<int>
{
typedef struct TrueType ispod;
};
template<>
struct IsPoD<char>
{
typedef struct TrueType ispod;
};
template<> struct IsPoD<float>
{
typedef struct TrueType ispod;
};
template<> struct IsPoD<long>
{
typedef struct TrueType ispod;
};
template <class T>
class SeqList
{
public:
SeqList()
:_a(nullptr),_size(0),_capacity(0)
{}
SeqList(const SeqList<T>& s)
{
allocate(_a,s._a,s._size,s._size,typename IsPoD<T>::ispod());
}
SeqList& operator=(SeqList<T>object)
{
std::swap(object._a,_a);
_size = object._size;
_capacity = object._capacity;
}
~SeqList()
{
delete []_a;
}
void PushBack(const T& x);
void PopBack();
void Insert(size_t pos, const T& x);
void Erase(size_t pos);
T& operator[](size_t pos);
void Print();
protected :
void allocate(T*&dest,T*src,size_t N,size_t size,struct TrueType)
{
dest = new T[N];//N代表要申请多少个元素的空间大小,size代表src共有多少个元素
memmove(dest,src,size*sizeof(T));
}
#if 1
void allocate(T*&dest,T*src,size_t N,size_t size,struct FalseType)
{
dest = new T[N];
for(int i=0;i<size;++i)
{
dest[i]=src[i];
}
}
#endif
void CheckCapicity()
{
if(_size==_capacity)
{
T * tmp=nullptr;
allocate(tmp, _a, _size*2+5, _size, typename IsPoD<T>::ispod());
delete [] _a;
_a = tmp;
}
}
private:
T* _a;
size_t _size;
size_t _capacity;
};
template<class T>
void SeqList<T>::PushBack(const T&x)
{
CheckCapicity();
_a[_size++] = x;
}
template<class T>
void SeqList<T>::PopBack()
{
this->_size--;
}
template<class T>
void SeqList<T>::Insert(size_t pos,const T&x)
{
CheckCapicity();
for(size_t i=this->_size-1;i >=pos ; --i)
{
_a[i+1] = _a[i];
}
_a[pos]=x;
++_size;
}
template<class T>
void SeqList<T>::Erase(size_t pos)
{
for(size_t i=pos;i<this->_size;++i)
{
_a[i]=_a[i+1];
}
this->_size--;
}
template<class T>
T& SeqList<T>::operator[](size_t pos)
{
assert(pos<_size);
return _a[pos];
}
template<class T>
void SeqList<T>::Print()
{
for(int i=0;i<this->_size;++i)
{
cout<<this->_a[i]<<endl;
}
}
#if 1
// 带头节点的双向循环链表--思考结构的优势
template <class T>
struct ListNode
{
ListNode(const T&x=T())
{
_data = x;
_next = nullptr;
_prev = nullptr;
}
~ListNode()
{}
T _data;
ListNode* _next;
ListNode* _prev;
};
template<class T>
class List
{
typedef ListNode<T> Node;
public:
List()
:_head(nullptr)
{}
List(const List& l)
{
allocate(_head,l._head);
}
List& operator=(const List l)
{
std::swap(l._head,_head);
return *this;
}
~List()
{
Node * pCur = _head;
Node * prev = nullptr;
while(prev!=_head) // 哇 写的完美 nullptr 也处理掉了 太开心了,还只进行了一次内存引用 呀咯 无敌勒
{
prev = pCur; // 这个赋值 要处理 只有一个节点的情况
pCur = pCur -> _next;
delete prev;
prev = pCur;
}
}
void PushBack(const T& x);
void PopBack();
void PushFront(const T& x);
void PopFront();
void Insert(Node* pos, const T& x);
void Erase(Node* pos);
void Print();
protected:
void allocate(Node*&Dest,Node*Src)
{
if(Dest==nullptr||Dest == Src)
return ;
Node * pCur = nullptr;
Node * prev =nullptr;
Dest = pCur = prev = new Node(Src);
Src = Src->_next;
while(Src)
{
pCur = pCur->_next = new Node(Src);
pCur->_prev = prev;
prev = pCur;
Src = Src->_next;
}
pCur->_next = Src;
Src ->_prev = pCur;
}
private:
Node* _head;
};
template<class T>
void List<T>::PushBack(const T&x)
{
if(_head==nullptr)
{
_head = new Node(x);
_head->_prev = _head;
_head->_next = _head;
return ;
}
Node * prev = this->_head->_prev;
Node * pCur = prev->_next = new Node(x);
pCur ->_prev = prev;
pCur ->_next = _head;
_head ->_prev = pCur;
}
template<class T>
void List<T>::Print()
{
if(_head)
{
Node * pCur = _head;
while(pCur->_next!=_head)
{
cout<<pCur->_data<<" ";
pCur = pCur->_next;
}
cout<<pCur->_data;
}
cout<<endl;
}
template<class T>
void List<T>::Erase(Node*pos)
{
assert(pos);
Node * prev = pos->_prev;
Node * pnext = pos->_next;
prev->_next = pnext;
pnext->_prev = prev;
delete pos;
if(_head==pos)
_head = pnext;
}
template<class T>
void List<T>::Insert(Node*pos,const T&x)
{
assert(pos);
Node * prev = pos->_prev;
Node * pCur = prev->_next = new Node(x);
pos->_prev = pCur;
pCur->_prev = prev;
pCur->_next = pos;
}
template<class T>
void List<T>::PushFront(const T&x)
{
PushBack(x);
}
template<class T>
void List<T>::PopBack()
{
assert(_head);
if(_head==_head->_next)
{
delete _head;
_head = nullptr;
}
else
{
Node * del = this->_head->_prev;
Node * prev = del->_prev;
prev->_next = _head;
_head->_prev = prev;
delete del;
}
}
template<class T>
void List<T>::PopFront()
{
assert(_head);
if(_head==_head->_next)
{
delete _head;
_head = nullptr;
return ;
}
Node*Pnext = _head->_next;
Node*Prev=Pnext->_prev = _head->_prev;
Prev->_next = Pnext;
Pnext->_prev = Prev;
delete _head;
_head = Pnext;
}
void TestSeqList()
{
SeqList<string> s2;
s2.PushBack("aaaaaaaaaaaaaaaaaaa");
s2.PushBack("bbb");
s2.PushBack("ccc");
s2.PushBack("ddd");
s2.Print();
SeqList<int> s3;
s3.PushBack(1);
s3.PushBack(2);
s3.PushBack(3);
s3.PushBack(4);
s3.Print();
}
void TestList()
{
List<string> s1;
s1.PushBack("1111");
s1.PushBack("2222");
s1.PushBack("3333");
s1.PushBack("4444");
s1.PushBack("5555");
s1.PushBack("6666");
s1.Print();
s1.PopBack();
s1.PopFront();
s1.PopBack();
s1.PopBack();
s1.PopFront();
s1.PopFront();
s1.Print();
}
int main()
{
// TestSeqList();
TestList();
return 0;
}
细节
首先STL下的所有容器的构造函数,都是分俩步来进行的。第一步申请内存simple_alloc去做这个东西,第二步填充元素,fill_XX函数来做。这个fill_xx函数做了类型萃取,内置类型直接通过memmove拷贝,ADT类型通过inplacementnew来实现构造。
所谓inplacementnew,置位new表达式就是在已有的内存上构造对象,它是调用了目标类的拷贝构造来完成的对象构造。
析构的时候,也是根据类型萃取,如果是内置类型直接释放,如果是ADT类型会对每个变量都调用其析构函数。