一. 空间配置器基本原理
空间配置器原理和实现见空间配置器的实现
二. 利用trace跟踪调试
对于内存池的内部实现过程还是比较复杂的,虽然代码量,函数比较简单。但是调用过程可能比较复杂。这时,如果我们选择debug调试,过程会相当的繁琐,需要仔细记录调用堆栈过程以及数据流向,逻辑变更等。
所以,就使用Trace进行跟踪,打印数据流向,逻辑走向,文件,函数,方法,行位置。那么我们就能根据这个记录进行程序的排错以及调优了。
利用宏打印文件,行,函数位置,然后利用可变参数列表方式接收代码中具体位置的记录跟踪。
#include <stdarg.h>
#define _DEBUG_
static string GetFileName(const string& path)
{
char ch = '/' ;
#ifdef _WIN32
ch = '\\';
#endif
size_t pos = path.rfind(ch);
if (pos == string::npos)
return path;
else
return path.substr(pos + 1);
}
inline static void _trace_debug(const char * funcName, const char * fileName, int line, char* format, ...)
{
#ifdef _DEBUG_
fprintf(stdout, "[%s:%d]%s", GetFileName(fileName).c_str(), line, funcName);
// 输出用户信息
va_list args;
va_start(args, format);
vfprintf(stdout, format, args);
va_end(args);
#endif
}
#define __TRACE_DEBUG(...) _trace_debug(__FUNCDNAME__, __FILE__, __LINE__, __VA_ARGS__);
测试结果如下:
通过对测试结果的计算和代码相比对,程序无bug,并能正确申请和分配空间。
三. 给容器vector和list分配空间
vector和list是标准序列式容器,也是最简单的容器,选择vector和list作为测试容器,一方面是比较简单容易,另一方面是vector需要连续空间,可以测试一级空间配置器,list是链表,是小结点,可以测试二级空间配置器。
测试结果:
在利用空间配置器为vector和list分配空间后,vector和list可以正确运行和使用。
vector和list代码见后面。
四. 空间配置器的问题
- 内存池的空间何时释放 ?
答:在二级空间配置器中,空间没有释放的记录,没有归还给系统。一般情况下,内存池的空间会挂到自由链表中。在程序结束时,空间释放。 - 内碎片的问题,自由链表所挂区块都是8的整数倍,因此当我们需要非8倍数的区块,往往会导致浪费,比如我只要1字节的大小,但是自由链表最低分配8块,也就是浪费了7字节,我以为这也就是通常的以空间换时间的做法,这一点在计算机科学中很常见。
- 假如我不断的开辟小块内存,最后将整个heap上的内存都挂在了自由链表上,但是都没有用这些空间,再想要开辟一个大块内存的话会开辟失败。
- 但是总体来看,空间配置器的效率还是很高的。
vector和list代码:
#pragma once
#include "Allocate.h"
#include "Iterator.h"
#include "Uninitialized.h"
#include "Construct.h"
template<class T, class alloc = Alloc>
class Vector
{
public:
// * 值类型
typedef T ValueType;
// * 指针类型
typedef ValueType* Pointer;
typedef const ValueType* ConstPointer;
// * 引用类型
typedef ValueType& Reference;
typedef const ValueType& ConstReference;
// * 迭代器类型
typedef ValueType* Iterator;
typedef const ValueType* ConstIterator;
// * 反向迭代器类型
typedef ReverseIterator<ConstIterator> ConstReverseIterator;
typedef ReverseIterator<Iterator> ReverseIterator;
typedef size_t SizeType;
typedef ptrdiff_t DifferenceType; //ptrdiff_t用来保存两个指针减法操作的结果
// * 向量的专属迭代器,每次分配或者释放一个ValueType类型的空间,使用alloc分配
typedef SimpleAlloc<ValueType, alloc> DataAllocator;
protected:
/* 向量的管理
start指向开始,
finish指向最后一个数据的下一个位置
endOfStorage指向最后一个空间的下一个位置
*/
Iterator start;
Iterator finish;
Iterator endOfStorage;
public:
// * 几个基本函数(构造,析构,拷贝构造,赋值运算符)
// * 构造函数
Vector()
: start(0), finish(0), endOfStorage(0)
{}
// * 构造一个向量,有n个值为value的元素
Vector(SizeType n, const ValueType& value)
{
Fill_Initialize(n, value);
}
// 对只有一个数据成员的类,单参数的构造函数容易发生隐式转换,前面的explicit可以防止这个发生,
//但是对于Vecotr有三个数据成员的类,前面的explicit可加可不加
explicit Vector(SizeType n)
{
Fill_Initialize(n, T());
}
// * 由一段区间构造一个向量
Vector(ConstIterator first, ConstIterator last)
{
SizeType n = 0;
Distance(first, last, n);
start = AllocateAndCopy(n, first, last);
finish = start + n;
endOfStorage = finish;
}
// * 拷贝构造
Vector(const Vector<T, alloc>& x)
{
start = AllocateAndCopy(x.Size(), x.Begin(), x.End());
finish = start + x.Size();
endOfStorage = finish;
}
// * 析构函数
~Vector()
{
// * 析构所有元素
Destroy(start, finish);
// * 释放所有空间
Deallocate();
}
/* 赋值运算符的传统写法 */
//Vector<T, alloc> & operator=(const Vector<T, alloc>& x)
//{
// if (&x != this)
// {
// SizeType sizeOfX = x.Size();
// if (sizeOfX > Capacity()) // * x的size比我当前的容量还大,需要申请空间
// {
// Iterator tmp = AllocateAndCopy(x.End() - x.Begin(), x.Begin(), x.End());
//
// // * 释放原有空间
// Destroy(start, finish);
// Deallocate();
// // * 修改范围
// start = tmp;
// endOfStorage = start + sizeOfX;
// }
// else if (Size() > x.Size()) // * x的size比较小,只拷x.Size()个元素,当前向量中之后的元素析构掉
// {
// Iterator end = copy(x.Begin(), x.End(), start);
// Destroy(end, finish);
// }
// else // * x的size比较大,前半段拷贝,后半段先初始化在拷贝(如果是POD类型,该函数还是调用的copy)
// {
// copy(x.Begin(), x.End(), start);
// UninitializedCopy(x.Begin() + Size(), x.End(), finish);
// }
// finish = start + sizeOfX;
// }
// return *this;
//}
/* 赋值运算符的简洁写法 */
Vector<T, alloc> & operator=(Vector<T, alloc> x)
{
Swap(x);
return *this;
}
public:
// * 向量的对外接口
Iterator Begin()
{
return start;
};
ConstIterator Begin()const
{
return start;
};
Iterator End()
{
return finish;
};
ConstIterator End()const
{
return finish;
};
/*
RBegin()
RBegin()
REnd()
REnd()
*/
/* * func: 返回的是现有元素个数 */
SizeType Size()const
{
return End() - Begin();
}
SizeType MaxSize()
{
return SizeType(SizeType(-1) / sizeof(T));
}
/* * func: 修改向量的现有元素个数至newSize,如果现有元素个数newSize,则删除后面一部分;
反之在尾端插入一部分 x */
void Resize(SizeType newSize, ValueType& x)
{
if (newSize < Size())
Erase(Begin() + newSize, finish);
else
Insert(End(), newSize - Size(), x);
}
/* * func: 返回的是容量,即向量所有申请的空间大小 */
SizeType Capacity()const
{
return endOfStorage - start;
};
bool Empty()const
{
return End() == Begin();
};
Reference operator[](SizeType n)
{
return *(Begin() + n);
};
ConstReference operator[](SizeType n)const
{
return *(Begin() + n);
}
Reference Front()
{
return *Begin();
}
ConstReference Front() const
{
return *Begin();
}
Reference Back()
{
return *(End() - 1);
}
ConstReference Back() const
{
return *(End() - 1);
}
/* * func: 保留,把向量的 容量 扩充 至n,只有当向量的当前容量小于n时,该函数才会做事情 */
void Reserve(SizeType n)
{
if (Capacity() < n)
{
// * 拷贝数据到一个新的地址,该空间长度为 n
SizeType oldSize = Size();
Iterator tmp = AllocateAndCopy(n, start, finish);
// * 销毁原有空间
Destroy(start, finish);
Deallocate();
// * 重新修改范围
start = tmp;
finish = start + oldSize;
endOfStorage = start + n;
}
}
/* * func: 在向量尾部插入数据 x */
void PushBack(const T& x)
{
if (finish != endOfStorage)
Construct(finish++, x);
else
Insert_Aux(End(), x);
}
/* * func: 尾部删除一个元素 */
void PopBack()
{
--finish;
Destroy(finish);
}
/* * func: 删除向量中的所有元素,但是不销毁向量 */
void Clear()
{
Erase(Begin(), End());
}
/* * func: 交换两个向量 */
void Swap(Vector<T, Alloc> &x)
{
std::swap(start, x.start);
std::swap(finish, x.finish);
std::swap(endOfStorage, x.endOfStorage);
}
/* * func: 在position处插入元素 x */
Iterator Insert(Iterator position, const ValueType& x)
{
// * 有空闲空间,并且插入点是在最后面,直接构造一个对象
if (finish != endOfStorage && position == End())
{
Construct(position, x);
++finish;
}
// * 如果没有空闲空间 | position是向量中间某一个位置,需要申请空间 | 往后移动元素
else
Insert_Aux(position, x);
return position;
}
/* * func: 在position处插入默认元素 */
Iterator Insert(Iterator position)
{
return Insert(position, T());
}
/* * func: 在position位置插入一段区间 [first, last) */
void Insert(Iterator position, ConstIterator first, ConstIterator last)
{
// * 只有当[first, last)不空时才去做一些事
if (first != last)
{
SizeType n = 0;
Distance(first, last, n);
if (endOfStorage - finish > n) // 剩余空间够用
{
SizeType elemsAfter = finish - position;
Iterator oldFinish = finish;
if (elemsAfter > n)
{
// * 拷贝finish之前的n个数据到finish
UninitializedCopy(finish - n, finish, finish);
finish += n;
// * 剩余的elemsAfter-n个元素往后拷贝
copy_backward(position, oldFinish - n, oldFinish);
// * 填充新数据到指定位置
copy(first, last, position);
}
else // elemsAfter <= n
{
// * 先把[first, last)区间的后面几个元素拷贝到原区间尾部
UninitializedCopy(first + elemsAfter, last, finish);
finish += n - elemsAfter;
// * 把elemsAfter个剩余元素拷贝到尾部
UninitializedCopy(position, oldFinish, finish);
finish += elemsAfter;
// * 把elemsAfter个新元素拷贝到position
copy(first, first + elemsAfter, position);
}
} /* if endOfStorage - finish > n */
else // * endOfStorage - finish <= n 说明空间不够用
{
// * 申请空间
SizeType oldSize = Size();
SizeType len = oldSize + max(oldSize, n);
Iterator newStart = DataAllocator::Allocate(len);
Iterator newFinish = newStart;
// * 拷贝position之前的元素到新空间, 拷贝[start, position)到newStart
newFinish = UninitializedCopy(start, position, newStart);
// * 追加新数据到新空间的尾部,拷贝[first, last)到newFinish
newFinish = UninitializedCopy(first, last, newFinish);
// * 追加position之后的元素到新空间的尾部,拷贝[position, finish)到newFinish
newFinish = UninitializedCopy(position, finish, newFinish);
// * 释放原空间
Destroy(start, finish);
Deallocate();
// * 更改范围
start = newStart;
finish = newFinish;
endOfStorage = start + len;
} /* else */
} /* if first != last */
}
/* * func: 在position位置插入n个值为x的元素 */
void Insert(Iterator position, SizeType n, ValueType& x)
{
if (n != 0)
{
if (endOfStorage - finish >= n) // 剩余空间够用
{
ValueType xCopy = x;
SizeType elemsAfter = finish - position;
Iterator oldFinish = finish;
if (elemsAfter > n)
{
// * 拷贝finish之前的n个数据到finish
UninitializedCopy(finish - n, finish, finish);
finish += n;
// * 剩余的elemsAfter-n个元素往后拷贝
copy_backward(position, oldFinish - n, oldFinish);
// * 填充新数据到指定位置
fill(position, position + n, xCopy);
}
else // elemsAfter <= n
{
// * 先把[first, last)区间的后面几个元素拷贝到原区间尾部
UninitializedFill_n(finish, n - elemsAfter, xCopy);
finish += n - elemsAfter;
// * 把elemsAfter个剩余元素拷贝到尾部
UninitializedCopy(position, oldFinish, finish);
finish += elemsAfter;
// * 把elemsAfter个新元素拷贝到position
fill(position, oldFinish, xCopy);
}
} /* if endOfStorage - finish > n */
else // * endOfStorage - finish <= n 说明空间不够用
{
// * 申请空间
SizeType oldSize = Size();
SizeType len = oldSize + max(oldSize, n);
Iterator newStart = DataAllocator::Allocate(len);
Iterator newFinish = newStart;
// * 拷贝position之前的元素到新空间, 拷贝[start, position)到newStart
newFinish = UninitializedCopy(start, position, newStart);
// * 追加新数据到新空间的尾部,拷贝[first, last)到newFinish
newFinish = UninitializedFill_n(newFinish, n, x);
// * 追加position之后的元素到新空间的尾部,拷贝[position, finish)到newFinish
newFinish = UninitializedCopy(position, finish, newFinish);
// * 释放原空间
Destroy(start, finish);
Deallocate();
// * 更改范围
start = newStart;
finish = newFinish;
endOfStorage = start + len;
} /* else */
} /* if n != 0 */
}
/* * func: 删除position位置的元素,返回position位置,现在该位置的值编程删除前position的下一个元素 */
Iterator Erase(Iterator position)
{
if (position + 1 != finish)
copy(position + 1, finish, position);
--finish;
Destroy(finish);
return position;
}
/* * func: 删除向量中的[first, last)区间的元素,返回原来的first位置 */
Iterator Erase(Iterator first, Iterator last)
{
// * 覆盖用[last, finish)区间的元素覆盖[first, last), newFinish返回last的下一个位置
Iterator newFinish = copy(last, finish, first);
// * 删除后面的重复元素
Destroy(newFinish, finish);
// * 修改新区间
finish = newFinish;
return first;
}
/* * func: 把[first, last)区间的元素赋值给向量,
如果[first, last)区间的元素还没有当前的Size()大,就删除向量后面的所有元素 */
void Assign(ConstIterator first, ConstIterator last)
{
Iterator it = Begin();
// * 为了复用节点,首先把一些值赋给向量开始的一段元素
for (; it != End() && first != last; ++it, ++first)
*it = *first;
Erase(it, End());
for (; first != last; ++first)
Insert(End(), *first);
}
protected:
// 一些内部接口
/* * func: 在position处插入元素 x */
template<class T>
void Insert_Aux(Iterator position, const T& x)
{
if (finish != endOfStorage)
{
Construct(finish, *(finish - 1));
++finish;
T x_copy = x;
// * 把[position, finish-2)的元素拷贝到以 finish-1) 为末地址的空间【从后往前拷贝】
copy_backward(position, finish - 2, finish - 1);
//大致定义:
//copy_backward(first, last, result) {hile (first != last) *--result = *--last;}
*position = x_copy;
}
else // * finish == endOfStorage,已有空间不够
{
const SizeType old_size = Size();
const SizeType len = old_size != 0 ? 2 * old_size : 1;
Iterator new_start = DataAllocator::Allocate(len);
Iterator new_finish = new_start;
// * 先拷贝插入点的前一部分
//new_finish = UninitializedCopy(start, position, new_start);
new_finish = uninitialized_copy(start, position, new_start);
// * 在position插入当前新值
Construct(new_finish, x);
++new_finish;
// * 拷贝插入点的后一部分
//new_finish = UninitializedCopy(position, finish, new_finish);
new_finish = uninitialized_copy(position, finish, new_finish);
// * 销毁之前的空间
Destroy(Begin(), End());
//DataAllocator::Deallocate();
Deallocate();
// * 修正当前的范围
start = new_start;
finish = new_finish;
endOfStorage = new_start + len;
} /* else */
} /* Insert_Aux */
/* * func: 向量初始化用,开辟n个空间,并初始化成value */
void Fill_Initialize(SizeType n, const ValueType& value)
{
start = AllocateAndFill(n, value);
finish = start + n;
endOfStorage = finish;
}
/* * func: 分配n个空间,并在刚分配的空间内填充n个值为value的元素 */
Iterator AllocateAndFill(SizeType n, const ValueType& value)
{
Iterator result = DataAllocator::Allocate(n);
UninitializedFill_n(result, n, value);
return result;
}
/* * func: 分配n个空间,并把[first, last)区间的元素拷贝到刚分配的空间内 */
template<class ForwardIterator>
Iterator AllocateAndCopy(SizeType n, ForwardIterator first, ForwardIterator last)
{
Iterator result = DataAllocator::Allocate(n);
// [first, last) 拷贝到以result开始的地方
UninitializedCopy(first, last, result);
return result;
}
/* * func: 如果向量有容量,就释放所有空间 */
void Deallocate()
{
if (start)
DataAllocator::Deallocate(start, endOfStorage - start);
}
}; /* Vector */
#pragma once
#include <stddef.h> // * ptrdiff_t
#include "Allocate.h"
#include "Construct.h"
#include "Iterator.h"
// * 链表节点
template<class T>
struct __ListNode
{
T _data; // * 值类型
struct __ListNode<T>* _next; // * 指向下一个节点
struct __ListNode<T>* _prev; // * 指向前一个节点
__ListNode(const T& data, struct __ListNode<T>* next = NULL, struct __ListNode<T> *prev = NULL)
:_data(data)
, _next(next)
, _prev(prev)
{}
};
// * 链表的迭代器
template<class T, class Ref, class Ptr>
struct __ListIterator
{
typedef __ListIterator<T, T&, T*> Iterator;
typedef __ListIterator<T, const T&, const T*> ConstIterator;
typedef __ListIterator<T, Ref, Ptr> Self;
// * 迭代器的五种型别
typedef BidirectionalIteratorTag IteratorCategory;
typedef T ValueType;
typedef Ptr Pointer;
typedef Ref Reference;
typedef ptrdiff_t DifferenceType;
// * 重定义指针类型
typedef __ListNode<T>* LinkType;
typedef size_t SizeType;
typedef ptrdiff_t Difference;
// * 几个构造函数
__ListIterator() :_node(NULL) {}
// * 用一个节点的指针构造
__ListIterator(LinkType x) :_node(x) {}
// * 拷贝构造
__ListIterator(const Iterator &x) :_node(x._node) {}
// * 迭代器的几个操作
bool operator==(const Self &x) { return _node == x._node; }
bool operator!=(const Self &x) { return !operator==(x); }
Reference operator*() { return (*_node)._data; }
Pointer operator->() { return &(operator*()); }
Self& operator++() // * 前置++
{
_node = (*_node)._next;
return *this;
}
Self operator++(int)
{
Self tmp = *this;
++(*this);
return tmp;
}
Self& operator--() // * 前置--
{
_node = (*_node)._prev;
return *this;
}
Self operator--(int)
{
Self tmp = *this;
(*this)--;
return *this;
}
// * 迭代器的数据成员(一个指向链表节点的指针)
LinkType _node;
};
template <class T, class Ref, class Ptr>
inline BidirectionalIteratorTag
IteratorCategory(const __ListIterator<T, Ref, Ptr>&) // ****** only for List
{
return BidirectionalIteratorTag();
}
template <class T, class alloc = Alloc>
class List
{
typedef __ListNode<T> ListNode;
public:
typedef T ValueType;
typedef ValueType Pointer;
typedef const ValueType ConstPointer;
typedef ValueType& Reference;
typedef const ValueType& ConstReference;
typedef __ListNode<T> ListNode;
typedef ListNode* LinkType;
typedef SimpleAlloc<ListNode, alloc> ListNodeAllocator; // * list的专属空间配置器,构造节点用
typedef size_t SizeType;
typedef ptrdiff_t DifferenceType;
// * 迭代器
typedef typename __ListIterator<T, T&, T*>::Iterator Iterator;
typedef typename __ListIterator<T, const T&, const T*>::ConstIterator ConstIterator;
// * 反向迭代器
typedef ReverseIterator<ConstIterator> ConstReverseIterator;
typedef ReverseIterator<Iterator> ReverseIterator;
protected:
LinkType _node; // ****** 链表的句柄,一个头节点的指针
public:
// * 几个基本函数(构造,析构,拷贝构造,赋值运算符)
List() {
EmptyInitialize();
}
List(SizeType n, const T& value) { FillInitialize(n, value); }
// * 对只有一个数据成员的类,单参数的构造函数容易发生隐士转换,前面的explicit可以防止这个发生
explicit List(SizeType n) { FillInitialize(n, T()); }
// * 用其他链表的任意一段区间构造一个新链表
List(ConstIterator first, ConstIterator last) { RangeInitialize(first, last); };
// * 用数组的任意一段区间构造一个新链表
List(const T* first, const T* last) { RangeInitialize(first, last); }
// * 用任意类型的数据区间构造一个新链表
#ifdef __STL_MEMBER_TEMPLATES
template<class InputIterator>
List(InputIterator first, InputIterator last) { RangeInitialize(first, last); }
#endif
// * 拷贝构造
List(const List<T> &x)
{
EmptyInitialize();
Insert(Begin(), x.Begin(), x.End());
}
~List()
{
Clear();
//delete _node;
Destroy(_node);
_node = NULL;
}
/* * func: 赋值运算符重载 (传统写法) */
// List<T>& operator=(const List<T> &x)
// {
// if (this != &x)
// {
// Iterator first1 = Begin(), last1 = End();
// ConstIterator first2 = x.Begin(), last2 = x.End();
//
// while (first1 != last1 && first2 != last2)
// {
// *first1++ = *first2++;
// }
//
// if (first1 == last1) // * 前面的链表先走到头,需要把x中剩下的节点拷贝到当前链表的最后
// Insert(last1, first2, last2);
// else
// Erase(first1, last1);
// }
//
// return *this;
// }
/* * func: 赋值运算符重载 (简便写法) 简洁直观,但是不能避免自赋值 */
List<T>& operator=(List<T> x)
{
Swap(x);
return *this;
}
public:
// * List的对外接口
Iterator Begin() { return Iterator((*_node)._next); }
ConstIterator Begin() const { return Iterator((*_node)._next); }
Iterator End() { return Iterator(_node); }
ConstIterator End() const { return Iterator(_node); }
ReverseIterator RBegin() { return ReverseIterator(End()); }
ConstReverseIterator RBegin()const { return ConstReverseIterator(End()); }
ReverseIterator REnd() { return ReverseIterator(Begin()); }
ConstReverseIterator REnd() const { return ConstReverseIterator(Begin()); }
bool Empty() { return _node->_next == _node; }
Reference Front() { return *Begin(); }
ConstReference Front() const { return *Begin(); }
Reference Back() { return *End(); }
ConstReference Back() const { return *End(); }
void Swap(List<T> <) { std::swap(_node, lt._node); }
// * List 基本操作的实现
/* * func: 在position位置前插入值为x的节点 */
Iterator Insert(Iterator &position, const T& x)
{
LinkType tmp = CreateNode(x);
// * 该节点与前后节点接合
tmp->_prev = position._node->_prev;
tmp->_next = position._node;
position._node->_prev = tmp;
tmp->_prev->_next = tmp;
// * 返回新的节点的迭代器
return Iterator(tmp);
}
/* * func: 在position前面插入n个值为x的元素 */
void Insert(Iterator &position, SizeType n, const T& x)
{
for (; n > 0; --n)
Insert(position, x);
}
// * 函数体中把n强转成SizeType(size_t)类型的原因:如果不强转,会递归调用自己,因为不会退出,从而导致栈溢出
//void Insert(Iterator &position, int n, const T& x) { Insert(position, (SizeType)n, x); }
//void Insert(Iterator &position, long n, const T& x) { Insert(position, (SizeType)n, x); }
/* * func: 为用其他链表的一段区间去初始化链表而设计, 在position前插入 [first, last) 之间的元素 */
void Insert(Iterator position, ConstIterator first, ConstIterator last)
{
for (; first != last; ++first)
Insert(position, *first);
}
/* * func: 为用数组初始化链表而设计 */
void Insert(Iterator position, const T* first, const T* last)
{
for (; first != last; ++first)
Insert(position, *first);
}
/* * func: 为用任意类型的一段区间去初始化链表而设计 */
#ifdef __STL_MEMBER_TEMPLATES
template<class InputIterator>
void Insert(Iterator position, InputIterator first, InputIterator last)
{
for (; first != last; ++first)
Insert(position, *first);
}
#endif
/* * func: 删除指定为位置position处的元素 */
Iterator Erase(Iterator &position)
{
LinkType NextNode = position._node->_next;
LinkType PrevNode = position._node->_prev;
NextNode->_prev = PrevNode;
PrevNode->_next = NextNode;
// * 删除该节点
//delete position._node;
ListNodeAllocator::Deallocate(position._node);
// * 返回该节点后一个节点的迭代器
return Iterator(NextNode);
}
/* * func: 删除指定区间 [first, last) 之间的元素 */
Iterator Erase(Iterator &first, Iterator &last)
{
while (first != last)
Erase(first++);
return last;
}
/* * func: 重新更改链表size到newSize,如果newSize 比 size大,后面补x*/
void Resize(SizeType newSize, const ValueType& x)
{
SizeType len = 0;
Iterator it = Begin();
for (; it != End() && len < newSize; ++it, ++len)
;
if (len == newSize)
Erase(it, End());
else
Insert(End(), newSize - len, x);
}
/* * func: 重新更改链表size到newSize */
void Resize(SizeType newSize) { Resize(newSize, T()); }
/* * func: 把list本身用[first, last)这段区间替换掉 */
template<class InputIterator>
void Assign(InputIterator first, InputIterator last)
{
Iterator it = Begin();
// * 为了复用节点,首先把一些值赋给list开始的一段元素
for (; it != End() && first != last; ++it, ++first)
*it = *first;
Erase(it, End());
for (; first != last; ++first)
Insert(it, *first);
}
/* * func: 清空链表所有元素,但是不摧毁链表 */
void Clear()
{
LinkType cur = _node->_next;
LinkType del = NULL;
while (cur != _node) // * 依次删除除头节点以外的所
{
del = cur;
cur = cur->_next;
//delete del;
ListNodeAllocator::Deallocate(del);
}
_node->_next = _node;
_node->_prev = _node;
}
/* * func: 删除指定元素值的节点 */
void Remove(const T& value)
{
Iterator cur = Begin();
Iterator end = End();
Iterator del; // * 临时变量,记录要删除的节点
while (cur != end)
{
if (*cur == value) // * 注意迭代器失效的问题
{
del = cur;
++cur;
Erase(del);
}
else
++cur;
}
}
void Unique()
{
Iterator first = Begin();
Iterator end = End();
if (first == end) return;
Iterator next = first;
while (++next != end)
{
if (*first != *next)
first = next;
else
{
Erase(next);
next = first;
}
}
}
/* * func: 把链表x合并到当前链表中 (不会创建新节点),当前链表与x合并之前都必须有序 */
void Merge(List<T> &x)
{
Iterator first1 = Begin(), last1 = End();
Iterator first2 = x.Begin(), last2 = x.End();
Iterator next;
while (first1 != last1 && first2 != last2)
{
if (*first2 < *first1) // * first2的数据较小,需要合并
{
next = first2;
Transfer(first1, first2, ++next);
first2 = next; // * 合并之后需要把first2指向x中的下一个节点(这时不能使用first2++,因为first2所指节点已经接到当前链表中了)
}
else
++first1;
} /* while */
// * 到这里的情况有两种:first1还没走到头但first2到头了 或 first1与first2同时走到头; first1走到头了但first2还没走到头
// * 对于第一种情况,无关紧要
// * 对于第二种情况,要把x中剩余的节点接到当前链表的最后面
if (first2 != last2)
Transfer(last1, first2, last2);
}
/* * func: 对链表进行排序,主要使用单向快排 */
void Sort()
{
_Sort(Begin(), End());
}
void Reverse()
{
Iterator first = Begin(); // * 第一个节点
if (first._node == _node || first._node->_next == _node) // * 没有节点或者只有一个节点,直接返回
return;
Iterator prev; // * 临时变量,记录当前转接的第一
Iterator end = End(); // * 循环的结束条件
++first;
while (first != end) // * first 从第二个数据节点开始
{
prev = first;
++first;
Transfer(Begin(), prev, first);
}
}
/* * func: 把链表x接合到当前的position位置前 */
void Splice(Iterator &position, List<T> &x)
{
if (!x.Empty())
Transfer(position, x.Begin(), x.End());
}
/* * func: 把i所指节点接到position前面的位置 */
void Splice(Iterator &position, Iterator i)
{
Iterator j = i;
++j;
// * 自己接到自己前面,或者前一个节点接到当前节点的前面,直接
if (position == i || position == j)
return;
Transfer(position, i, j);
}
/* * func: 把 [first, last) 所指区间接到position前面 */
void Splice(Iterator &position, Iterator first, Iterator last)
{
if (first != last)
Transfer(position, first, last);
}
void PushFront(const T& x) { Insert(Begin(), x); }
void PushBack(const T& x) { Insert(End(), x); }
void PopFront() { Erase(Begin()); }
void PopBack() { Erase(--End()); }
protected:
// * List的几个内部接口
/* * func: 申请一个节点的内存,并调用节点的构造函数,最后返回该节点的指针 */
LinkType CreateNode(const T& value)
{
LinkType tmp = GetNode();
Construct(tmp, value);
return tmp;
}
/* * func: 申请一个链表节点的空间(只申请空间并不构造) */
LinkType GetNode()
{
return ListNodeAllocator::Allocate();
}
/* * func: 初始化空的链表 (其实就是构造一个头节点) */
void EmptyInitialize()
{
_node = CreateNode(T());
_node->_next = _node;
_node->_prev = _node;
}
/* * func: 构造函数用 */
void FillInitialize(SizeType n, const T& value)
{
EmptyInitialize();
Insert(Begin(), n, value);
}
/* * func: 把[first, last)内的所有元素移动到position之前 */
// *ps: 区间不可重叠,即position不能位于[first, last)区间内部
void Transfer(Iterator position, Iterator first, Iterator last)
{
if (position != last)
{
// * 总共有三处指针(总共6个)需要修改
// * 三个向右的方向
last._node->_prev->_next = position._node;
position._node->_prev->_next = first._node;
first._node->_prev->_next = last._node;
// * 三个向左的方向
LinkType tmp = position._node->_prev;
position._node->_prev = last._node->_prev;
last._node->_prev = first._node->_prev;
first._node->_prev = tmp;
}
}
void RangeInitialize(ConstIterator first, ConstIterator last)
{
EmptyInitialize();
Insert(Begin(), first, last);
}
void RangeInitialize(const T* first, const T* last)
{
EmptyInitialize();
Insert(Begin(), first, last);
}
#ifdef __STL_MEMBER_TEMPLATES
template<class InputIterator>
void RangeInitialize(InputIterator first, InputIterator last)
{
EmptyInitialize();
Insert(Begin(), first, last);
}
#endif
void _Sort(Iterator first, Iterator last)
{
Iterator tmp = first;
if (tmp == last || ++tmp == last)
return;
Iterator mid = first;
Iterator cur = first;
ValueType key = *cur;
++cur;
while (cur != last)
{
if (*cur < key)
{
if (++mid != cur)
std::swap(*cur, *mid);
}
++cur;
}
std::swap(*first, *mid);
_Sort(first, mid);
_Sort(++mid, last);
}
};
// * 几个全局函数
template<class T>
inline bool operator==(const List<T> &x, const List<T> &y)
{
typedef typename List<T>::LinkType LinkType;
LinkType end1 = x._node;
LinkType end2 = y._node;
LinkType f1 = end1->_next;
LinkType f2 = end2->_next;
for (; f1 != end1 && f2 != end2; f1 = f1->_next, f2 = f2->_next)
{
if (f1->_data != f2->_data)
return false;
}
// ****** 循环结束后还不能直接返回真,这时要看两个链表是不是一样
return f1 == end1 && f2 == end2;
}
template<class T>
inline bool operator<(const List<T> &x, const List<T> &y)
{
return true;
}
template<class T>
inline void Swap(const List<T> &x, const List<T> &y)
{
x.Swap(y);
}