本文主要探讨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/bash
if [ -f ./Makefile ]
then
make clean
fi
cmake .
make
echo "---------------------------------"
./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/bash
if [ -f ./Makefile ]
then
make clean
fi
cmake .
make
echo "---------------------------------"
./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;
}
结果示例: