本文主要探讨c++相关知识。
模板是对类型参数化
函数模板特化不是模板函数重载
allocator(空间配置器):内存开辟释放,对象构造析构
优先调用对象成员方法实现的运算符重载函数,其次全局作用域找
迭代器遍历访问元素,调用erase,insert方法后,当前位置到容器末尾元素的所有迭代器全部失效
malloc只开辟空间,new还可初始化
malloc开辟内存失败返回nullptr,new(malloc实现)抛出bad_alloc异常
delete(free实现)先调析构函数再free,无析构函数delete和free相同
new和delete也是函数重载符调用
除了对象的其他类型变量的数组和单个变量可混用delete/delete []
对象在new开辟内存时会多开辟4字节来存储对象个数,使用delete []时才可正确调用析构函数
对象池:短时间内多次使用用一块内存(new/delete)
demo1:
vector实现
结构图:
run.sh
#!/bin/bashif [ -f ./Makefile ]
thenmake clean
ficmake .makeecho "---------------------------------"./pro
CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.28) #最低版本要求SET(CMAKE_CXX_COMPILER "g++-11") #设置g++编译器PROJECT(CLASS) #设置工程名MESSAGE(STATUS "CPP test") #打印消息ADD_EXECUTABLE(pro test.cpp) #生成可执行文件
clean.sh
rm -rf CMakeCache.txt CMakeFiles Makefile cmake_install.cmake *.o pro
test.cpp
#include <iostream>//空间配置器
template<typename T>
struct Allocator
{//开辟空间T* Allocate(size_t size){return (T*)malloc(sizeof(T) * size);}//释放空间void des_Allocate(void *p){free(p);}//构造元素void construct(T *p,const T& value){new (p) T(value);}//释放元素void des_construct(T *p){p->~T();}
};template<typename T,typename Alloc = Allocator<T>>
class vector
{public:vector(int size = 5){first = allocator.Allocate(size);last = first;end = first + size;}~vector(){for(T *p = first; p != last; p++){allocator.des_construct(p);}allocator.des_Allocate(first);first = last = end = nullptr;}vector(const vector<T> &rhs){first = allocator.Allocate(rhs.end - rhs.first);last = first + (rhs.last - rhs.first );end = first + (rhs.end - rhs.first);for(T *p = first; p != last; p++){allocator.construct(p,*(rhs.first + (p - first)));}}vector &operator=(const vector<T> &rhs){if(this == &rhs)return *this;delete [] first;first = allocator.Allocate(rhs.end - rhs.first);last = first + (rhs.last - rhs.first );end = first + (rhs.end - rhs.first);for(T *p = first; p != last -1; p++){allocator.construct(p,*(rhs.first + (p - first)));}}void push_back(const T& value){if(full())expand();allocator.construct(last,value);last++;}void pop_back(){if(empty())return;allocator.des_construct(last);last--;}T front() const{return *first;}T back() const{return *(last - 1);}bool full() const {return last == end;}bool empty() const{return first == last;}T* data() const{return first;}size_t size() const{return (last - first);}T &operator[](unsigned int index) const{if(index > size())throw "out of range";return first[index];}T &at(unsigned int index){if(index > size())throw "out of range";return first[index];}size_t capacity() const{return (end - first);}//迭代器class iterator{public:friend class vector<T,Alloc>;iterator(vector<T,Alloc> *pvec = nullptr,T *ptr = nullptr):pvec(pvec),ptr(ptr){Iterator_Base *itb = new Iterator_Base(this,pvec->head.next);pvec->head.next = itb;};T &operator*() const{if(pvec == nullptr)throw "iterator invaild";return *ptr;}T *operator->() const{if(pvec == nullptr)throw "iterator invaild";return ptr;}T *operator++() {if(pvec == nullptr)throw "iterator invaild"; return ++ptr;}T *operator++(int) {if(pvec == nullptr)throw "iterator invaild";return ptr++;}T *operator--(){if(pvec == nullptr)throw "iterator invaild";return --ptr;}T *operator--(int){if(pvec == nullptr)throw "iterator invaild";return ptr--;}bool operator==(const iterator &it){//迭代器为空,两个不同迭代器if(pvec == nullptr || pvec != it.pvec)throw "iterator incompatable";return ptr == it.ptr;}bool operator!=(const iterator &it) const{//迭代器为空,两个不同迭代器if(pvec == nullptr || pvec != it.pvec)throw "iterator incompatable";return ptr != it.ptr;}private:T* ptr;vector<T,Alloc> *pvec;};//头迭代器iterator ibegin(){return iterator(this,first);}//尾迭代器iterator iend(){return iterator(this,last);}//迭代器失效,释放元素资源void iterator_clear(T *first,T *last){Iterator_Base *pre = &(this->head);Iterator_Base *it = this->head.next;while(it != nullptr){if(it->cur->ptr > first && it->cur->ptr <= last){it->cur->pvec = nullptr;pre->next = it->next;delete it;it = pre->next;}else{pre = it;it = it ->next;}}}//元素插入方法,迭代器失效iterator insert(iterator it, const T &val){iterator_clear(it.ptr - 1,last);T *p = last;while (p > it.ptr){allocator.construct(p, *(p-1));allocator.des_construct(p - 1);p--;}allocator.construct(p, val);last++;return iterator(this, p);}//元素擦除方法,迭代器失效iterator erase(iterator it){iterator_clear(it.ptr - 1,last);T *p = it.ptr;while (p < last-1){allocator.des_construct(p);allocator.construct(p, *(p+1));p++;}allocator.des_construct(p);last--;return iterator(this, it.ptr);}private:T *first;T *last;T *end;Alloc allocator;//迭代器指针,迭代器失效释放资源和重构迭代器struct Iterator_Base{Iterator_Base(iterator *c = nullptr,Iterator_Base *next = nullptr):cur(c),next(next){};iterator *cur;Iterator_Base *next;};Iterator_Base head;//扩容方法void expand(){int size = end - first;T* tmp = allocator.Allocate(2 * size);for(int i = 0;i < size;i++){allocator.construct(tmp + i,*(first + i));allocator.des_construct(first + i);}allocator.des_Allocate(first);first = tmp;last = tmp + size;end = tmp + (2 * size);}};class Test
{public:Test(){};Test(int num):num(num){};int num;
};int main()
{Test t1(1),t2(2),t3(3),t4(4),t5(5),t6(6);vector<Test> v;v.push_back(t1);v.push_back(t2);v.push_back(t3);v.push_back(t4);v.push_back(t5);v.push_back(t6);vector<Test> v1(v);vector<Test> v2 = v1;vector<Test> v3 = v1;std::cout << "front():" << v2.front().num << std::endl;std::cout << "back():" << v2.back().num << std::endl;std::cout << "data():" << v2.data()->num << std::endl;std::cout << "size():" << v2.size() << std::endl;std::cout << "[]:" << v2[1].num << std::endl;std::cout << "at():" << v2.at(1).num << std::endl;std::cout << "capacity():" << v2.capacity() << std::endl;v2.pop_back();v2.pop_back();v2.pop_back();v2.pop_back();v2.pop_back();v2.pop_back();std::cout << "v:";for(auto it = v.ibegin();it != v.iend();it++){std::cout << it->num << " ";}std::cout << std::endl;for(auto it = v.ibegin();it != v.iend();it++){if(it->num == 2){it = v.insert(it,7);++it;}}std::cout << "v:";for(auto it = v.ibegin();it != v.iend();it++){std::cout << it->num << " ";}std::cout << std::endl;std::cout << "v1:";for(auto it = v1.ibegin();it != v1.iend();++it){std::cout << it->num << " ";}std::cout << std::endl;for(auto it = v1.ibegin();it != v1.iend();++it){if(it->num == 4){it = v1.erase(it);++it;}}std::cout << "v1:";for(auto it = v1.ibegin();it != v1.iend();++it){std::cout << it->num << " ";}std::cout << std::endl;std::cout << "v2:";for(auto it = v2.ibegin();it != v2.iend();it++){std::cout << it->num << " ";}std::cout << std::endl;auto it_v3_end = v3.iend();std::cout << "*(it_v3_end--):" << (it_v3_end--)->num << std::endl;std::cout << "*(--it_v3_end):" << (--it_v3_end)->num << std::endl;return 0;
}
结果示例:
demo2:
对象池
结构图:
run.sh
#!/bin/bashif [ -f ./Makefile ]
thenmake clean
ficmake .makeecho "---------------------------------"./pro
CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.28) #最低版本要求SET(CMAKE_CXX_COMPILER "g++-11") #设置g++编译器PROJECT(CLASS) #设置工程名MESSAGE(STATUS "CPP test") #打印消息ADD_EXECUTABLE(pro test.cpp) #生成可执行文件
clean.sh
rm -rf CMakeCache.txt CMakeFiles Makefile cmake_install.cmake *.o pro
test.cpp
#include <iostream>
#include <time.h>template<typename T>
class Queue
{public:Queue(){front = rear = new QueueItem(); }~Queue(){QueueItem *tmp = front;while(tmp != nullptr){front = front->next;delete tmp;tmp = front;}}void push(const T& val){QueueItem *tmp = new QueueItem(val);rear->next = tmp;rear = tmp;}void pop(){if(empty())return;QueueItem* tmp = front->next;front->next = tmp->next;if (front->next == nullptr){rear = front;}delete tmp;}bool empty(){return front == rear;}private:struct QueueItem{QueueItem(T data = T()):data(data),next(nullptr){};static void * operator new(size_t size){if(itempool == nullptr ){itempool = (QueueItem*)new char[sizeof(QueueItem) * POOL_SIZE];QueueItem *tmp = itempool;for(;tmp < itempool + POOL_SIZE - 1;tmp++){tmp->next = tmp + 1;} tmp->next = nullptr;}QueueItem *tmp = itempool;itempool = itempool->next;return tmp;}static void operator delete(void *p){QueueItem* tmp = (QueueItem*)p; tmp->next = itempool;itempool = tmp;}T data;QueueItem *next;static QueueItem* itempool;static const unsigned int POOL_SIZE = 1000000;};static int num;QueueItem *front;QueueItem *rear;
};template<typename T>
typename Queue<T>::QueueItem* Queue<T>::QueueItem::itempool = nullptr;class Test
{public:Test(){};Test(int n){};~Test(){};private:
};int main()
{Queue<Test> t;for(int i = 0;i < 1000000;i++){t.push(Test(i));t.pop();}std::cout << "run time: " <<(double)clock() / CLOCKS_PER_SEC << "s" << std::endl;return 0;
}
结果示例: