c++理解(三)

news/2024/12/21 18:38:41/

        本文主要探讨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;
}

结果示例:


http://www.ppmy.cn/news/1556989.html

相关文章

Guava 库中的 `Multiset` 是一个允许元素重复的集合

Guava 库中的 Multiset 是一个允许元素重复的集合。它继承自 Collection 接口&#xff0c;提供了额外的方法来处理元素的计数。以下是一些使用 Guava Multiset 的基本代码示例&#xff1a; 引入 Guava 库 首先&#xff0c;确保你的项目中已经添加了 Guava 库的依赖。如果你使…

idea无法识别文件,如何把floder文件恢复成model

前景&#xff1a; 昨天&#xff0c;我在之前的A1214模块包下新增了一个demo类&#xff0c;然后又新建了一个A1216模块&#xff0c;写了算法题&#xff0c;后面打算用git提交&#xff0c;发现之前的A1214模块下的demo类和新建的模块源文件都已经被追踪了&#xff0c;都是绿色的&…

STM32单片机芯片与内部33 ADC 单通道连续DMA

目录 一、ADC DMA配置——标准库 1、ADC配置 2、DMA配置 二、ADC DMA配置——HAL库 1、ADC配置 2、DMA配置 三、用户侧 1、DMA开关 &#xff08;1&#xff09;、标准库 &#xff08;2&#xff09;、HAL库 2、DMA乒乓 &#xff08;1&#xff09;、标准库 &#xff…

ts 内置类型与类型断言

ts 内置类型与类型断言 // 变量 函数不显式声明类型 会被推导为any // unknow和any 区别 any是代表自己可以是任何类型 unknown代表目前未确定是什么类型 但是将来会有一个确定类型 //一个 unknown 类型的变量可以再次赋值为任意其它类型&#xff0c;但只能赋值给 any 与 unkn…

5G 模组 RG200U常用AT命令

5G 模组 RG200 U常用AT命令 5G 模组 RG200 U常用AT命令 ATQCFG“usbnet”,3 ATQICSGP2,1,“”,“cmnet”,“”,1 APN ATQNETDEVCTL2,3,1 ATCFUN0 将 UE 设置为最小功能模式 ATCFUN1 将 UE 设置为全功能模式 ATQENG“servingcell” 查询服务小区信息 ATQNETDEVCTL1,3,1 拨…

基于Java的秦皇岛旅游景点管理系统

一、系统背景与目的 秦皇岛&#xff0c;作为中国著名的旅游城市&#xff0c;拥有丰富的自然景观和人文历史遗迹。为了提升秦皇岛旅游景点的管理效率和服务质量&#xff0c;基于Java的旅游景点管理系统应运而生。该系统旨在通过信息化手段&#xff0c;实现旅游景点的智能化管理…

咸虾米壁纸微信小程序下载图片到相册saveImageToPhotosAlbum功能修改

当我将咸虾米壁纸这个项目进行重构的时候&#xff0c;想要将图片资源变得小一点&#xff0c;所以在上传图片的时候均采用了webp格式的&#xff0c;这样就导致再预览页面下载图片的时候出错了&#xff0c;之前使用的是uni.getImageInfo()这个API&#xff0c;该API不支持webp图片…

VSCode如何修改默认扩展路径和用户文件夹目录到D盘

在使用Visual Studio Code&#xff08;VSCode&#xff09;时&#xff0c;随着安装的扩展和用户数据的增多&#xff0c;C盘的空间可能会逐渐紧张。为了优化存储管理&#xff0c;将VSCode的默认扩展路径和用户文件夹目录迁移到D盘是一个有效的解决方案。以下是详细的操作步骤&…