当前位置: 首页 > news >正文

义乌城市投资建设集团网站做本地网站能做吗

义乌城市投资建设集团网站,做本地网站能做吗,广州公司建站模板,龙岗做网站哪里找目录示例版本1#xff1a;per-class allocator,1示例版本2#xff1a;per-class allocator,2最终版本#xff1a;static allocator针对版本三进行macro如果我们不针对对象做内存管理#xff0c;那么我们每次进行Foo* p new Foo(x);时总是会调用malloc函数。 尽管malloc函数… 目录示例版本1per-class allocator,1示例版本2per-class allocator,2最终版本static allocator针对版本三进行macro 如果我们不针对对象做内存管理那么我们每次进行Foo* p new Foo(x);时总是会调用malloc函数。 尽管malloc函数很快但是我们仍然有自己管理内存的必要。 在https://blog.csdn.net/qq_42604176/article/details/111234556中曾经记录到有些操作系统多次调用malloc函数会把原来很大的一块连续内存区域逐渐地分割成许多非常小而且彼此不相邻的内存区域也就是内存碎片。这也是一种隐患。 我们可以首先使用malloc函数申请一大段内存然后切割成若干个小块每次创建一个对象的时候就给一小块的内存。这样效率更高并且更容易管理。 并且如果没有经过特殊设计一次创建对象就调用一次malloc一次malloc就会得到两个cookie(8个字节)。创建多个对象的时候这样就会比较浪费空间。 内存池设计的目的就是要提高速度和降低浪费。 示例版本1per-class allocator,1 下面是示例 #includecstddef #includeiostream using namespace std;class Screen { public:Screen(int x):i(x) {};int get() {return i;}void* operator new(size_t);void operator delete(void*,size_t);//... private:Screen* next;static Screen* freeStore;static const int screenChunk; private:int i; }; Screen* Screen::freeStore 0; const int Screen::screenChunk 24;出于对内存管理的考虑我们需要挖一大块内存并且内存里面的小块需要用指针联系到一起。所以可以看到上面class内部会有一个next指针指向Screen类型的对象。但是这样会有一个遗憾因为多出来一个指针导致空间又浪费掉了。 接下来是函数的重载。核心的操作步骤就是单向链表的操作。将空闲的内存做成链表每次开辟新内存的话就将链表中的一个分配出去。 void* Screen::operator new(size_t size) {Screen *p;if(!freeStore) {//linked list 是空的所以申请了一大块内存size_t chunk screenChunk * size; //一次挖24个对象的内存//将指针转型freeStore p reinterpret_castScreen*(new char[chunk]);//将一大块分割成小块当作linked list串接起来for(;p ! freeStore[screenChunk - 1]; p)p-next p 1;p-next 0;}p freeStore;freeStore freeStore-next;return p; }如果回收的话析构对象将内存重新放置回链表中 注意这里是将回收的内存指针放在链表头部因为这样操作比较快。只需要动头指针就行了。注意这里的内存并没有还给操作系统而是将使用过的内存穿成一个链表。 void Screen::operator delete(void *p,size_t) {//将delete object 插回free list前端(static_castScreen*(p))-next freeStore;freeStore static_castScreen*(p); }测试函数 cout sizeof(Screen) endl; //16size_t const N 100; Screen* p[N];for(int i 0; i N; i)p[i] new Screen(i);//输出前10个pointers比较其间隔 for(int i 0; i 10; i)cout p[i] endl;for(int i 0; i N; i)delete p[i]; 效果 可以看出每个类之间的内存间隔是16确实没有cookie的内存。 16 00000280B9B21CF0 00000280B9B21D00 00000280B9B21D10 00000280B9B21D20 00000280B9B21D30 00000280B9B21D40 00000280B9B21D50 00000280B9B21D60 00000280B9B21D70 00000280B9B21D80 如果我们不对两个函数进行重载得到的结果如下由于电脑操作系统是多进程的所以可能在内存分配的时候有其他任务执行导致内存不是连续的估摸着间隔应该是5*16。 16 000001BA32211920 000001BA322120A0 000001BA32211A10 000001BA32211970 000001BA32211C90 000001BA32212460 000001BA322124B0 000001BA32212500 000001BA32211EC0 000001BA322119C0 在侯捷老师的PPT上是VC6、GNU环境下的结果如下 示例版本2per-class allocator,2 这个版本主要是利用union对第一版本的指针进行优化。 关于union这里做一个简单回顾毕竟基本没用过这东西。 具体细节可以参考https://blog.csdn.net/yuyanggo/article/details/49819667?utm_mediumdistribute.pc_relevant.none-task-blog-baidujs_baidulandingword-2spm1001.2101.3001.4242 同一个内存段可以用来存放几种不同类型的成员但在每一个时刻只能存在其中一种而不是同时存放几种。也就是说每一瞬间只有一个成员起作用其它的成员不起作用即不是同时都存在和起作用。 共用体变量中起作用的成员是最后一个存放的成员在存入一个新的成员后原有的成员就失去作用。 #include iostream using namespace std;union test {char mark;long num;float score; }a;int main() {// coutaendl; // wronga.mark b;couta.markendl; // 输出bcouta.numendl; // 98 字符b的ACSII值couta.scoreendl; // 输出错误值a.num 10;couta.markendl; // 输出换行 非常感谢suxin同学的指正couta.numendl; // 输出10couta.scoreendl; // 输出错误值a.score 10.0;couta.markendl; // 输出空couta.numendl; // 输出错误值couta.scoreendl; // 输出10return 0; }由于union中的所有成员起始地址都是一样的所以a.mark、a.num和a.score的值都是一样的。 由于union里面的东西共享内存所以不能定义静态、引用类型的变量。 在union里也不允许存放带有构造函数、析构函数和复制构造函数等的类的对象但是可以存放对应的类对象指针。编译器无法保证类的构造函数和析构函数得到正确的调用由此就可能出现内存泄漏。 接下来看第二个版本 class Airplane { private:struct AirplaneRep {unsigned long miles;char type;}; private:union {AirplaneRep rep; //此指针指向使用中的对象Airplane* next; //此指针指向free list上的对象}; //这些方法不是重点 public:unsigned long getMiles() {return rep.miles;}char getType() {return rep.type;}void set(unsigned long m, char t) {rep.miles m;rep.type t;} //重载new和delete public:static void* operator new(size_t size);static void operator delete(void* deadObject, size_t size); private:static const int BLOCK_SIZE;static Airplane* headOfFreeList; }; Airplane* Airplane::headOfFreeList; const int Airplane::BLOCK_SIZE 512; new的重载和第一个版本相似 void* Airplane::operator new(size_t size) {//在继承发生时可能size大小有误if(size ! sizeof(Airplane))return ::operator new(size);Airplane* p headOfFreeList;if(p) //如果p有效就把链表头部向下移headOfFreeList p-next;else{//如果链表已空申请一大块内存Airplane* newBlock static_castAirplane*(::operator new(BLOCK_SIZE * sizeof(Airplane)));//将小块穿成一个freelistfor(int i 1; i BLOCK_SIZE - 1; i)newBlock[i].next newBlock[i1];newBlock[BLOCK_SIZE - 1].next 0;p newBlock;headOfFreeList newBlock[1];}return p; }delete版本几乎与第一个版本一样都存在着没有将内存归还给操作系统的问题这个并不属于内存泄漏因为内存仍然掌握在我们手中。 //operator delete截获一个内存块 //如果大小正确就把它加到freelist前端 void Airplane::operator delete(void* deadObject, size_t size) {if(deadObject 0) return;if(size ! sizeof(Airplane)) {::operator delete(deadObject);return;}Airplane* carcass static_castAirplane*(deadObject);carcass-next headOfFreeList;headOfFreeList carcass; }最终版本static allocator 刚刚我们都是针对一个class单独重载它的new和delete这样会导致代码的重复性。我们将刚刚的动作抽象出来放到一个class里面。 每个allocator object 都是分配器它体内维护一个freelist不同的allocator objects维护者不同的freelists。 class allocator { private:struct obj {struct obj* next;}; public:void* allocate(size_t);void deallocate(void*,size_t); private:obj* freeStore nullptr;const int CHUNK 5; //这里小一些以便观察 };void allocator::deallocate(void* p,size_t) {//将*p收回插入free list 前端((obj*)p)-next freeStore;freeStore (obj*)p; }void* allocator::allocate(size_t size) {obj* p;if(!freeStore) {//linked list为空于是申请一大块size_t chunk CHUNK * size;freeStore p (obj*)malloc(chunk);//将分配得来的一大块当作linked list//串接起来for(int i 0; i (CHUNK - 1); i) {p-next (obj*)((char*)p size);p p-next;}p-next nullptr; }p freeStore;freeStore freeStore-next;return p; }下面是是类调用分配器 每个allocator object 都是分配器它体内维护一个freelist不同的allocator objects维护不同的freelists 所有与内存相关的细节由allocator接管。我们的工作是让application classes正确运作。 class Foo { public:long L;string str;static allocator myAlloc; public:Foo(long l):L(1){}static void* operator new(size_t size) {return myAlloc.allocate(size);}static void operator delete(void* pdead,size_t size) {return myAlloc.deallocate(pdead,size);} }; allocator Foo::myAlloc;如上所示具体的内存分配的细节都不再由应用类所知晓。 测试代码如下注意这里不要使用using namespace std;因为标准库里也有allocator。 #includecstddef #includeiostream//using namespace std; namespace static_allocator {class allocator{private:struct obj {struct obj* next;};public:void* allocate(size_t);void deallocate(void*, size_t);private:obj* freeStore nullptr;const int CHUNK 5; //这里小一些以便观察};void allocator::deallocate(void* p, size_t){//将*p收回插入free list 前端((obj*)p)-next freeStore;freeStore (obj*)p;}void* allocator::allocate(size_t size){obj* p;if (!freeStore) {//linked list为空于是申请一大块size_t chunk CHUNK * size;freeStore p (obj*)malloc(chunk);//将分配得来的一大块当作linked list//串接起来for (int i 0; i (CHUNK - 1); i) {p-next (obj*)((char*)p size);p p-next;}p-next nullptr;}p freeStore;freeStore freeStore-next;return p;}class Foo {public:long L;std::string str;static allocator myAlloc;public:Foo(long l) :L(1) {}static void* operator new(size_t size) {return myAlloc.allocate(size);}static void operator delete(void* pdead, size_t size) {return myAlloc.deallocate(pdead, size);}};allocator Foo::myAlloc;void test_static_allocator_3(){std::cout \n\n\ntest_static_allocator().......... \n;{Foo* p[100];std::cout sizeof(Foo) sizeof(Foo) std::endl;for (int i 0; i 23; i) { //23,任意數, 隨意看看結果 p[i] new Foo(i);std::cout p[i] p[i]-L std::endl;}//Foo::myAlloc.check();for (int i 0; i 23; i) {delete p[i];}//Foo::myAlloc.check();}} }int main() {static_allocator::test_static_allocator_3();return 0; }打印效果如下 可以看到allocator每一次调用malloc都是一次性取5个元素。所以每5个元素一定的是相邻的。可以从效果图的倒数第三个与倒数第四个之间看出。 重点关注这个写法。 针对版本三进行macro 具体步骤如下将黄色部分替换成蓝色部分即可。 每次使用的话直接在类内部调用两个宏就行了。 需要注意一个知识点 #define后面的是续行符表示下面一行是紧接着当前行的一般用于将十分长的代码语句分几zhuan段写语句本身要shu求必须是一行。 要注意\后面除了换行回车不能有任何字符空格也不行 #define DECLARE_POOL_ALLOC() \ public: \void* operator new(size_t size) { return myAlloc.allocate(size); } \void operator delete(void* p) { myAlloc.deallocate(p, 0); } \ protected: \static allocator myAlloc; // IMPLEMENT_POOL_ALLOC -- used in class implementation file #define IMPLEMENT_POOL_ALLOC(class_name) \ allocator class_name::myAlloc; // in class definition file class Foo {DECLARE_POOL_ALLOC() public: long L;string str; public:Foo(long l) : L(l) { } }; //in class implementation file IMPLEMENT_POOL_ALLOC(Foo) // in class definition file class Goo {DECLARE_POOL_ALLOC() public: complexdouble c;string str; public:Goo(const complexdouble x) : c(x) { } }; //in class implementation file IMPLEMENT_POOL_ALLOC(Goo)
http://www.pierceye.com/news/308351/

相关文章:

  • 做外贸的社交网站怎么攻击网站吗
  • 网站布局手机百度网址大全
  • 企业网站做多大擦边球做网站挣钱
  • 网站怎么备份做网站建设要学多久
  • 怎样做买东西的网站外汇期货喊单网站怎么做的
  • 博客网站推荐郑州哪里做网站
  • 贵州建设职业技术学院网站网站开发 多语言
  • 网站后台管理系统怎么进重庆建设工程安全管理局网站
  • 移动网站开发的视频下载百度网盘下载官网
  • 在百度备案网站建设工程检测网
  • 广州企业网站营销电话公司网站怎么做啊
  • 如何利用视频网站做推广网站开发管理学什么
  • 福建漳发建设有限公司网站做网站申请什么商标
  • 专门做房产的网站上海网站开发毕业生
  • 网站域名已经解析但没有被百度等搜索引擎收录怎么办可以做投票功能的网站
  • 重庆网站设计总部什么是社交电商平台
  • 内容管理网站百度电商平台
  • 网站建设 万网网站统计插件
  • 怎么个人网站设计网站建设 不违背
  • 图片下载网站郑州联通网站备案
  • 名师工作室网站建设 意义o2o新零售系统
  • 域名查询权威网站网页设计基础填空题及答案
  • 网站建设策划方案如何写新开传奇新服网
  • dedecms网站上传服务器不是空间网站正则表达式怎么做
  • 青岛企业建设网站企业南宁网站开发建设
  • 网站备案是先做网站还是做完了备案效果好的手机网站建设
  • 做企业宣传网站沈阳妇科检查去哪个医院较好
  • 网站为什么维护wordpress 交易平台
  • 南京 电子商务网站5118数据分析平台官网
  • 试析企业网站建设模式建网站的网络公司