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

沈阳网站制作列表网厦门酒店网站建设

沈阳网站制作列表网,厦门酒店网站建设,商业网站制作,做网站最好要买什么东西一般而言#xff0c;我们习惯的 C 内存配置操作和释放操作是这样的#xff1a; 1 class FOO{}; 2 FOO *pf new FOO; 3 delete pf; 我们看其中第二行和第三行#xff0c;虽然都是只有一句#xff0c;当是都完成了两个动作。但你 new 一个对象的时候两个动作是#xff…  一般而言我们习惯的 C 内存配置操作和释放操作是这样的 1 class FOO{}; 2 FOO *pf new FOO; 3 delete pf;   我们看其中第二行和第三行虽然都是只有一句当是都完成了两个动作。但你 new 一个对象的时候两个动作是先调用::operator new 分配一个对象大小的内存然后在这个内存上调用FOO::FOO()构造对象。同样当你 delete 一个对象的时候两个动作是先调用FOO::~FOO() 析构掉对象再调用::operator delete将对象所处的内存释放。为了精密分工STL 将allocator决定将这两个阶段分开。分别用 4 个函数来实现   1.内存的配置alloc::allocate();   2.对象的构造::construct();   3.对象的析构::destroy();   4.内存的释放alloc::deallocate();   其中的 construct() 和 destroy()定义在 STL的库文件中源代码如下 1 template class T2 inline void destroy(T* pointer) {3 pointer-~T(); //只是做了一层包装将指针所指的对象析构---通过直接调用类的析构函数4 }5 6 template class T1, class T27 inline void construct(T1* p, const T2 value) {8 new (p) T1(value); //用placement new在 p 所指的对象上创建一个对象value是初始化对象的值。9 } 10 11 template class ForwardIterator //destory的泛化版接受两个迭代器为参数 12 inline void destroy(ForwardIterator first, ForwardIterator last) { 13 __destroy(first, last, value_type(first)); //调用内置的 __destory(),value_type()萃取迭代器所指元素的型别 14 } 15 16 template class ForwardIterator, class T 17 inline void __destroy(ForwardIterator first, ForwardIterator last, T*) { 18 typedef typename __type_traitsT::has_trivial_destructor trivial_destructor; 19 __destroy_aux(first, last, trivial_destructor()); //trival_destructor()相当于用来判断迭代器所指型别是否有 trival destructor 20 } 21 22 23 template class ForwardIterator 24 inline void //如果无 trival destructor 那就要调用destroy()函数对两个迭代器之间的对象元素进行一个个析构 25 __destroy_aux(ForwardIterator first, ForwardIterator last, __false_type) { 26 for ( ; first last; first) 27 destroy(*first); 28 } 29 30 template class ForwardIterator //如果有 trival destructor 则什么也不用做。这更省时间 31 inline void __destroy_aux(ForwardIterator, ForwardIterator, __true_type) {} 32 33 inline void destroy(char*, char*) {} //针对 char * 的特化版 34 inline void destroy(wchar_t*, wchar_t*) {} //针对 wchar_t*的特化版   看到上面这么多代码大家肯定觉得 construct() 和 destroy() 函数很复杂。其实不然我们看到construct()函数只有几行代码。而 destroy() 稍微多点。但是这么做都是为了提高销毁对象时的效率。为什么要判断迭代器所指型别是否有 trival destructor然后分别调用不同的执行函数因为当你要销毁的对象很多的时候而这样对象的型别的destructor 都是 trival 的。如果都是用__destroy_aux(ForwardIterator first, ForwardIterator last, __false_type)来进行销毁的话很费时间因为没必要那样做。而当你对象的destructor 都是 non-trival 的时候你又必须要用__destroy_aux(ForwardIterator first, ForwardIterator last, __false_type)来析构。所以我们要判断出对象型别的destructor 是否为 trival然后调用不同的__destroy_aux。   说完 construct() 和 destory() 我们来说说 alloc::allocate() 和 alloc::deallocate()其源代码在 stl_alloc.h中。stl_alloc.h中代码设计的原则如下   1.向 system heap 要求空间   2.考虑多线程状态   3.考虑内存不足时的应变措施   4.考虑过多“小型区块”可能造成的内存碎片问题。   stl_alloc.h中的代码相当复杂不过没关系。我们今天只看其中的allocate() 和 deallocate()。在讲这两个函数之前我们还必须来了解一下SGI  STL(SGI限定词是STL的一个版本因为真正的STL有很多不同公司实现的版本我们所讨论的都是SGI版本) 配置器的工作原理   考虑到小型区块可能造成内存破碎问题(即形成内存碎片)SGI STL 设计了双层级配置器。第一层配置器直接使用malloc() 和 free().第二层配置器则视情况采用不同的策略但配置区块超过 128 bytes时调用第一级配置器。当配置区块小于 128 bytes时采用复杂的 memory pool 方式。下面我们分别简单的介绍一下第一级和第二级配置器 第一级配置器 _ _malloc_alloc_template   由于第一级配置器的配置方法比较简单代码也容易理解我在这里全部贴出 1 //以下是第第一级配置器2 template int inst3 class __malloc_alloc_template {4 5 private:6 7 //以下函数用来处理内存不足的情况8 static void *oom_malloc(size_t);9 10 static void *oom_realloc(void *, size_t); 11 12 static void (* __malloc_alloc_oom_handler)(); 13 14 public: 15 16 static void * allocate(size_t n) 17 { 18 void *result malloc(n); //第一级配置器直接使用malloc() 19 //如果内存不足则调用内存不足处理函数oom_alloc()来申请内存 20 if (0 result) result oom_malloc(n); 21 return result; 22 } 23 24 static void deallocate(void *p, size_t /* n */) 25 { 26 free(p); //第一级配置器直接使用 free() 27 } 28 29 static void * reallocate(void *p, size_t /* old_sz */, size_t new_sz) 30 { 31 void * result realloc(p, new_sz); //第一级配置器直接使用realloc() 32 //当内存不足时则调用内存不足处理函数oom_realloc()来申请内存 33 if (0 result) result oom_realloc(p, new_sz); 34 return result; 35 } 36 37 //设置自定义的out-of-memory handle就像set_new_handle()函数 38 static void (* set_malloc_handler(void (*f)()))() 39 { 40 void (* old)() __malloc_alloc_oom_handler; 41 __malloc_alloc_oom_handler f; 42 return(old); 43 } 44 }; 45 46 template int inst     47 void (* __malloc_alloc_templateinst::__malloc_alloc_oom_handler)() 0;  //内存处理函数指针为空等待客户端赋值 48 49 template int inst 50 void * __malloc_alloc_templateinst::oom_malloc(size_t n) 51 { 52 void (* my_malloc_handler)(); 53 void *result; 54 55 for (;;) { //死循环 56 my_malloc_handler __malloc_alloc_oom_handler; //设定自己的oom(out of memory)处理函数 57 if (0 my_malloc_handler) { __THROW_BAD_ALLOC; } //如果没有设定自己的oom处理函数毫不客气的抛出异常 58 (*my_malloc_handler)(); //设定了就调用oom处理函数 59 result malloc(n); //再次尝试申请 60 if (result) return(result); 61 } 62 } 63 64 template int inst 65 void * __malloc_alloc_templateinst::oom_realloc(void *p, size_t n) 66 { 67 void (* my_malloc_handler)(); 68 void *result; 69 70 for (;;) { 71 my_malloc_handler __malloc_alloc_oom_handler; 72 if (0 my_malloc_handler) { __THROW_BAD_ALLOC; } //如果自己没有定义oom处理函数则编译器毫不客气的抛出异常 73 (*my_malloc_handler)(); //执行自定义的oom处理函数 74 result realloc(p, n); //重新分配空间 75 if (result) return(result); //如果分配到了返回指向内存的指针 76 } 77 }   上面代码看似繁杂其实流程是这样的   1.我们通过allocate()申请内存通过deallocate()来释放内存通过reallocate()重新分配内存。   2.当allocate()或reallocate()分配内存不足时会调用oom_malloc()或oom_remalloc()来处理。   3.当oom_malloc() 或 oom_remalloc()还是没能分配到申请的内存时会转如下两步中的一步     a).调用用户自定义的内存分配不足处理函数(这个函数通过set_malloc_handler() 来设定)然后继续申请内存     b).如果用户未定义内存分配不足处理函数程序就会抛出bad_alloc异常或利用exit(1)终止程序。   看完这个流程再看看上面的代码就会容易理解多了 第二级配置器 _ _default_alloc_template   第二级配置器的代码很多这里我们只贴出其中的 allocate() 和 dellocate()函数的实现和工作流程(参考侯捷先生的《STL源码剖析》)而在看函数实现代码之前我大致的描述一下第二层配置器配置内存的机制。   我们之前说过当申请的内存大于 128 bytes时就调用第一层配置器。当申请的内存小于 128bytes时才会调用第二层配置器。第二层配置器如何维护128bytes一下内存的配置呢 SGI 第二层配置器定义了一个 free-lists,这个free-list是一个数组如下图      这数组的元素都是指针用来指向16个链表的表头。这16个链表上面挂的都是可以用的内存块。只是不同链表中元素的内存块大小不一样16个链表上分别挂着大小为    8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128 bytes的小额区块图如下       就是这样现在我们来看allocate()代码 static void * allocate(size_t n){obj * __VOLATILE * my_free_list;obj * __RESTRICT result;//要申请的空间大于128bytes就调用第一级配置if (n (size_t) __MAX_BYTES) {return(malloc_alloc::allocate(n));}//寻找 16 个free lists中恰当的一个my_free_list free_list FREELIST_INDEX(n);result *my_free_list;if (result 0) {//没找到可用的free list准备新填充free listvoid *r refill(ROUND_UP(n));return r;}*my_free_list result - free_list_link;return (result);};   其中有两个函数我来提一下一个是ROUND_UP()这个是将要申请的内存字节数上调为8的倍数。因为我们free-lists中挂的内存块大小都是8的倍数嘛这样才知道应该去找哪一个链表。另一个就是refill()。这个是在没找到可用的free list的时候调用准备填充free lists.意思是参考上图假设我现在要申请大小为 56bytes 的内存空间那么就会到free lists 的第 7 个元素所指的链表上去找。如果此时 #7元素所指的链表为空怎么办这个时候就要调用refill()函数向内存池申请N(一般为20个)个大小为56bytes的内存区块然后挂到 #7 所指的链表上。这样申请者就可以得到内存块了。当然这里为了避免复杂误导读者我就不讨论refill()函数了。allocate()过程图如下      学过链表的操作的人不难理解上图我就不再讲解。下面看deallocate()代码如下 1 static void deallocate(void *p, size_t n)2 {3 obj *q (obj *)p;4 obj * __VOLATILE * my_free_list;5 6 //如果要释放的字节数大于128则调第一级配置器7 if (n (size_t) __MAX_BYTES) {8 malloc_alloc::deallocate(p, n);9 return; 10 } 11 //寻找对应的位置 12 my_free_list free_list FREELIST_INDEX(n); 13 //以下两步将待释放的块加到链表上 14 q - free_list_link *my_free_list; 15 *my_free_list q; 16 }   deallocate()函数释放内存的步骤如下图   其实这就是一个链表的插入操作也很简单。不再赘述上面忘了给链表结点的结构体定义了如下 union obj{union obj * free_list_link;char client_date[1]; };   至此SGI STL的对象的构造与析构、内存的分配与释放就介绍完毕了。  转载于:https://www.cnblogs.com/zhuwbox/p/3699977.html
http://wiki.neutronadmin.com/news/50858/

相关文章:

  • 凡客建站百度旧版本下载
  • 大型门户网站源码爱战网关键词挖掘
  • 口碑好的邯郸网站建设网站建设与管理自考
  • 宠物医院网站建设甘肃购物网站建设
  • 做网站iiwokdw响应式网站模板下载
  • 网站制作制作网站登录按纽是灰色的
  • wordpress网站专题铸铁加工平台
  • 洛阳网站公司简单个人网站设计
  • 重庆网站开发公如何制作境外网站
  • 深圳网站建设 骏域网站建设平面设计接单网站有哪些
  • 财务费是指企业为施工生产深圳债务优化公司
  • 做微信h5的网站手机seo网站推广
  • 购买一个网站需要多少钱wordpress新用户无法注册
  • 网站的后台管理账号和密码国家备案网
  • 镇江网站排名优化价格青浦工厂网站建设
  • 杭州app开发公司定制外包怎么做公司网站优化
  • 精美网站制作广告传媒公司经营范围
  • 网站建设发展响应式网站模板dede
  • 自己做网站收费么网站三网合一案例
  • 闽侯福州网站建设网站建设自学网
  • 免费个人网站建设大全做门户网站用什么服务器
  • 苏州工业园区规划建设局网站找南昌网站开发公司电话
  • 网站建设规划书摘要500字用iis搭建网站
  • 做羞羞的网站网站建设方案 doc
  • 网站做的好不好看什么在百度做个卷闸门网站怎么做
  • 个人网站模板源码下载企业门户平台设计方案
  • 做设计的网站广州市网络seo外包
  • 网站建设案例查询泉州专门做网站
  • 上海韵茵网站建设线上培训平台
  • seo网站优化方案案例朔州建设机械网站