代码:Vector0.h
#ifndef VECTOR0_H
#define VECTOR0_H
#include "Ngx_pool.h"
#include <iostream>
using namespace std;
template<typename T>
class myallocater
{
public:
//construct构造 destroy析构
//allocate开辟内存 deallocate释放内存
myallocater() :count(0) {}
void construct(void *ptr, const T &val)
{
new (ptr)T(val);
}
void destroy(T *ptr)
{
ptr->~T();
}
//开辟内存
void* allocate(u_int size)
{
if (0 == count)
{
p.ngx_create_pool(4096);
++count;
}
return p.ngx_palloc(size);
}
//释放内存
void deallocate(void *ptr)
{
count = 0;
p.ngx_destroy_pool();
}
private:
NgxMemPool p;
int count;
};
template<typename T,typename Allocator=myallocater<T>>
class Vector
{
public:
typedef T value_type;
//template<typename T>
//默认构造的vector,底层没分配过内存
Vector() :mpVec(NULL), mSize(0), mCur(0) {}
Vector(int size, const T &val = T())
:mSize(size), mCur(0)
{
mpVec = (T*)_allocator.allocate(mSize*sizeof(T));
for (int i = 0; < msize; ++i)
{
_allocator.construct(mpVec + i, val);
}
}
//拷贝构造
Vector(const Vector<T> &src)
{
if (0 == src.mSize)
{
mpVec = (T*)_allocator.allocate(1 * sizeof(T));
mSize = 1;
mCur = 0;
}
else
{
T *p = (T*)_allocator.allocate(src.mSize * sizeof(T));
for (int i = 0; i < src.mCur; ++i)
{
_allocator.construct(p + i, src.mpVec[i]);
}
for (int i = 0; i < mCur; ++i)
{
_allocator.destroy(&mpVec[i]);
}
mSize = src.mSize;
mCur = src.mCur;
mpVec = p;
}
}
//operator=
Vector<T>& operator=(const Vector<T> &src)
{
if (this == &src)
throw "error";
for (int i = 0; i < mCur; ++i)
{
_allocator.destroy(&mpVec[i]);
}
mpVec = (T*)_allocator.allocate(src.mSize * sizeof(T));
for (int i = 0; i < src.mCur; ++i)
{
_allocator.construct(mpVec + i, src.mpVec[i]);
}
mSize = src.mSize;
mCur = src.mCur;
}
T& operator[](int index)
{
if (empty())
throw "error";
return mpVec[index];
}
~Vector()
{
if (!empty())
{
for (int i = 0; i < mCur; ++i)
{
_allocator.destroy(&mpVec[i]);
}
_allocator.deallocate(mpVec);
}
}
//末尾添加元素
void push_back(const T &val)
{
if (full())
reSize();
_allocator.construct(mpVec + mCur++, val);
}
//末尾删除
void pop_back()
{
_allocator.destroy(&mpVec[--mCur]);
}
T front()const { return mpVec[0]; }
T back()const { return mpVec[mCur - 1]; }
int size()const { return mCur; }
bool full()const { return mCur == mSize; }
bool empty()const { return 0 == mSize; }
//内存以2倍方式增长
void reSize()
{
if (empty())
{
mpVec = (T*)_allocator.allocate(1 * sizeof(T));
mSize = 1;
mCur = 0;
}
else
{
T *p = (T*)_allocator.allocate(mSize * 2 * sizeof(T));
for (int i = 0; i < mCur; ++i)
{
_allocator.construct(p + i, mpVec[i]);
}
for (int i = 0; i<mCur; ++i)
{
_allocator.destroy(&mpVec[i]);
}
mSize *= 2;
mpVec = p;
}
}
//定义当前容器的迭代器类型
class iterator
{
public:
typedef T value_type;
iterator(T *ptr = NULL) :p(ptr) {}
bool operator!=(const iterator &it)const { return p != it.p; }
bool operator==(const T &val)const { return *p == val; }
void operator=(const iterator &src) { return *p == *src.p; }
void operator++() { ++p; }
void operator--(int) { --p; }
T& operator*() { return *p; }
iterator operator+(const int size)const { return iterator(p + size); }
iterator operator-(const int size)const { return iterator(p - size); }
bool operator<(const iterator &src)const { return p < src.p; }
bool operator>(const iterator &src)const { return p > src.p; }
int operator-(const iterator &src)const { return p - src.p; }
T& operator[](const int index) { return p[index]; }
private:
T *p;
};
iterator begin()const { return iterator(mpVec); }
iterator end()const { return iterator(mpVec + mCur); }
/*
C++17次课作业:完成下面的三个接口
在it迭代器的位置,插入val元素
it位置合法:it在【first,last】范围
特殊情况:容器已经满了,插入要先扩容
it位置不合法: 插入失败,抛异常
*/
void insert(iterator &it, const T &val)
{
if (it < begin() || it > end())
throw "error";
if (this->full())
this->reSize();
*it = val;
}
/*
删除的容器,按值删除,按迭代器删除
*/
void erase(const T &val)
{
iterator it = this->begin();
for (; it != this->end(); ++it)
{
if (*it == val)
{
iterator tmp(it + 1);
for (; tmp != end(); ++tmp)
*(tmp - 1) = *tmp;
_allocator.destroy(mpVec + mCur - 1);
}
}
--mCur;
}
void erase(const iterator &it)
{
if (it < begin() || it > end())
throw "error";
iterator tmp(it + 1);
for (; tmp != end(); ++tmp)
*(tmp - 1) = *tmp;
_allocator.destroy(mpVec + mCur - 1);
--mCur;
}
private:
T *mpVec;
int mSize;
int mCur;
Allocator _allocator;
};
main.cpp
#include "Ngx_pool.h"
#include "Vector0.h"
#include <iostream>
#include <vld.h>
#include <Windows.h>
#include <time.h>
using namespace std;
template<typename Container>
void showContainer(Container &con)
{
Container::iterator it = con.begin();
for (; it != con.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
}
int main1()
{
Vector<int> MyIntVector;
for (int i = 0; i < 10; ++i)
{
MyIntVector.push_back(i);
}
showContainer(MyIntVector);
return 0;
}
int main(int argc, char* argv[])
{
Vector<int> vec1, vec2;
srand(time(0));
for (int i = 0; i < 10; ++i)
{
vec1.push_back(rand() % 100);
vec2.push_back(rand() % 100);
}
//默认从小到大排序 vector<int>::iterator list<int>::iteartor
//showContainer(vec1);
/*vec1.insert(vec1.begin(),99);
vec1.erase(vec1.begin());
showContainer(vec1);*/
//由小到大
//mysort(vec1.begin(), vec1.end(),smallpfunc<int>);
cout << "vec1:";
showContainer(vec1);
cout << "vec2:";
showContainer(vec2);
//Vector<int>::iterator it = myfind(vec1.begin(),vec1.end(),20);
/*
需要一种通用的方式,来遍历任何的容器 operator[]做不到的
通用: 怎么通用?是使用方式通用呢?还是所有容器共用一个迭代器呢?
数组operator[]
链表
二维数组
哈希表
红黑树
迭代器和容器是一一对应的,所以在设计上,把迭代器这个类,设计成容器类型的嵌套类性
*/
/*
1.需要在容器里面定义嵌套类性 iterator
2.给容器提供begin方法 iterator begin(); 把容器第0号位元素的迭代器返回回去
3.给容器提供end方法 iterator end(); 把容器末尾元素后继位置的迭代器返回回去
4.给迭代器提供operator!=
5.给迭代器提供operator++()
6.给迭代器提供operator*()
*/
/*Vector<int>::iterator it = vec1.begin();
for (; it != vec1.end(); ++it)
{
cout << *it << " ";
}
cout << endl;*/
return 0;
}
Ngx_pool.h
#ifndef NGX_POOL_H
#define NGX_POOL_H
typedef unsigned char u_char;
typedef unsigned int u_int;
typedef struct ngx_pool_s ngx_pool_t;
typedef struct ngx_pool_large_s ngx_pool_large_t;
const int MAX = 4096;
const int NGX_ALIGNMENT = sizeof(unsigned long);
#define ngx_align_ptr(p, a)\
(u_char *) (((unsigned int) (p) + ((unsigned int) a - 1)) & ~((unsigned int) a - 1))
typedef struct
{
u_char *last;
u_char *end;
ngx_pool_t *next;
u_int failed;
}ngx_pool_data_t;
struct ngx_pool_s
{
ngx_pool_data_t d;
ngx_pool_t *current;//指向当前内存的指针。
ngx_pool_large_t *large;
};
struct ngx_pool_large_s
{
ngx_pool_large_t *next;
void *alloc;
};
class NgxMemPool
{
public:
//创建ngx内存池
void ngx_create_pool(u_int size);
//销毁ngx内存池
void ngx_destroy_pool();
//重置内存池
void ngx_reset_pool();
//开辟内存,对齐
void* ngx_palloc(u_int size);
//开辟内存,不对齐
void* ngx_pnalloc(u_int size);
//把内存归还给内存池
bool ngx_pfree(void *p);
//开辟小块内存
void *ngx_palloc_small(u_int size, int align);
//开辟新的小块
void *ngx_palloc_block(u_int size);
//开辟大块内存
void *ngx_palloc_large(u_int size);
private:
ngx_pool_t *_pool;
};
#endif
Ngx_pool.cpp
#include "Ngx_pool.h"
#include "Vector0.h"
#include <iostream>
#include <vld.h>
#include <Windows.h>
#include <time.h>
using namespace std;
//创建ngx内存池
void NgxMemPool::ngx_create_pool(u_int size)
{
_pool = (ngx_pool_t*)malloc(size);
if (NULL == _pool)
{
return;
}
_pool->d.last = (u_char*)_pool + sizeof(ngx_pool_t);
_pool->d.end = (u_char*)_pool + size;
_pool->d.next = NULL;
_pool->d.failed = 0;
_pool->current = _pool;//当前指针位置
_pool->large = NULL;
}
//销毁ngx内存池
void NgxMemPool::ngx_destroy_pool()
{
//先释放large指向外部开辟的大内存
ngx_pool_large_t *pLarge;
for (pLarge = _pool->large; pLarge != NULL; pLarge = pLarge->next)
{
if (pLarge->alloc)
{
free(pLarge->alloc);
pLarge->next = NULL;
}
}
ngx_pool_t *p;
ngx_pool_t *n;
for (p = _pool, n = _pool->d.next;; p = n)
{
free(p);
p = NULL;
if (NULL == n)
{
break;
}
}
}
//重置内存池
void NgxMemPool::ngx_reset_pool()
{
ngx_pool_large_t *pLarge;//指向内存池外开辟的大块内存
ngx_pool_t *p;//指向内存池的指针
//先释放内存池外开辟的大块内存
for (pLarge = _pool->large; pLarge != NULL; pLarge = pLarge->next)
{
if (pLarge->alloc)
{
free(pLarge->next);
pLarge->alloc = NULL;
}
}
//再重置内存池中的内存
for (p = _pool; p; p = p->d.next)
{
p->d.last = (u_char*)p + sizeof(ngx_pool_t);
}
_pool->current = _pool;
}
//开辟内存,对齐
void* NgxMemPool::ngx_palloc(u_int size)
{
if (size <= MAX)
{
return ngx_palloc_small(size,0);
}
return ngx_palloc_large(size);
}
//把内存归还给内存池
bool NgxMemPool::ngx_pfree(void *p)
{
ngx_pool_large_t *pLarge;
//只检查是否是大内存块,如果是大内存块则释放
for (pLarge = _pool->large; pLarge; pLarge->next)
{
if (p == pLarge->alloc)
{
free(pLarge->alloc);
pLarge->alloc = NULL;
return true;
}
}
return false;
}
//开辟小块内存
void*NgxMemPool::ngx_palloc_small(u_int size,int align)
{
u_char *m;
ngx_pool_t *p;
p = _pool->current;
do {
m = p->d.last;
if (align)
{
m = ngx_align_ptr(m,NGX_ALIGNMENT);
}
if ((u_int)(p->d.end - m) >= size)
{
p->d.last = m + size;
return m;
}
} while (p);
//开辟内存过大,内存池中没有合适的内存,则重新开辟指定大小的内存块
return ngx_palloc_block(size);
}
//开辟新的小内存块
void *NgxMemPool::ngx_palloc_block(u_int size)
{
u_int psize;
u_char *m;
ngx_pool_t *pnew, *t;
psize = (u_int)(_pool->d.end-(u_char*)_pool);
m = (u_char*)malloc(psize);
if (NULL == m)
return NULL;
pnew = (ngx_pool_t*)m;
pnew->d.end = m + psize;
pnew->d.next = NULL;
pnew->d.failed = 0;
/*将m指针移动数据头的大小位置*/
m += sizeof(ngx_pool_data_t);
/*进行内存对齐计算*/
m = ngx_align_ptr(m, NGX_ALIGNMENT);
/*设置新内存块的last,即申请使用size大小的内存*/
pnew->d.last = m + size;
/*对链表进行整理current指针要重新确认*/
/*这里循环用来寻找最后一个节点 */
for (t = _pool->current; t->d.next != NULL; t = t->d.next)
{
if (t->d.failed++ > 4) //failed的值只在此处被修改
{
t->current = t->d.next; //失败4次以上移动current指针
}
}
/*在循环中next可能会指向NULL 所以current也可能会被置NULL*/
t->d.next = pnew; //将这次分配的内存块pnew加入该内存池链表中
/*对current确认为NULL时则重新确认位置*/
_pool->current = t->current ? t->current : pnew;
return m;
}
//开辟大块内存
void *NgxMemPool::ngx_palloc_large(u_int size)
{
void *p;
u_int n = 0;
ngx_pool_large_t *large;
// 直接在系统堆中分配一块空间
p = (void *)malloc(size);
if (p == NULL)
{
return NULL;
}
// 查找到一个空的large区,如果有,则将刚才分配的空间交由它管理
for (large = _pool->large; large; large = large->next)
{
if (NULL == large->alloc)
{
large->alloc = p;
return p;
}
if (n++ > 3)
{
break;
}
}
//为了提高效率, 如果在三次内没有找到空的large结构体,则创建一个
large = (ngx_pool_large_t*)ngx_palloc_small(size, 1);
if (NULL == large)
{
free(p);
return NULL;
}
large->alloc = p;
large->next = _pool->large;
_pool->large = large;
return p;
}